Skip to content

Commit 1927016

Browse files
committed
PoC test case passing, combined mappings to save gas
1 parent 26eebbe commit 1927016

File tree

9 files changed

+53
-33
lines changed

9 files changed

+53
-33
lines changed

contracts/ERC900/ERC900.sol

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pragma solidity ^0.4.24;
22

3+
34
/**
45
* @title ERC900 interface
56
* @dev see https://github.com/ethereum/EIPs/issues/900
@@ -17,7 +18,7 @@ contract ERC900 {
1718
function supportsHistory() public pure returns (bool);
1819

1920
// optional
20-
function lastStakedFor(address addr) public view returns (uint256);
21-
function totalStakedForAt(address addr, uint256 blockNumber) public view returns (uint256);
22-
function totalStakedAt(uint256 blockNumber) public view returns (uint256);
21+
// function lastStakedFor(address addr) public view returns (uint256);
22+
// function totalStakedForAt(address addr, uint256 blockNumber) public view returns (uint256);
23+
// function totalStakedAt(uint256 blockNumber) public view returns (uint256);
2324
}

contracts/ERC900/ERC900BasicStakeContainer.sol

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import "../ERC20/ERC20.sol";
55

66
import "../library/SafeMath.sol";
77

8+
89
/**
910
* @title ERC900BasicStakeContainer
1011
*/
@@ -13,30 +14,42 @@ contract ERC900BasicStakeContainer is ERC900 {
1314

1415
ERC20 stakingToken;
1516

16-
mapping (address => Stake) stakes;
17-
18-
// TODO: This data structure should change to represent "weight" instead of amount
19-
mapping (address => uint256) amountStakedFor;
17+
mapping (address => StakeContainer) addresses;
2018

2119
struct Stake {
2220
uint256 blockNumber;
2321
uint256 amount;
2422
bool exists;
2523
}
2624

25+
// To save on gas, rather than create a separate mapping for amountStakedFor & personalStake,
26+
// both data structures are stored in a single mapping for a given addresses.
27+
//
28+
// amountStakedFor consists of all tokens staked for a given address.
29+
// personalStake is the stake made by a given address.
30+
//
31+
// It's possible to have a non-existing personalStake, but have tokens in amountStakedFor
32+
// if other users are staking on behalf of a given address.
33+
struct StakeContainer {
34+
// TODO: This data structure should change to represent "weight" instead of amount
35+
uint256 amountStakedFor;
36+
37+
Stake personalStake;
38+
}
39+
2740
constructor(ERC20 _stakingToken) public {
2841
stakingToken = _stakingToken;
2942
}
3043

3144
function stake(uint256 _amount, bytes _data) public {
32-
require(!stakes[msg.sender].exists, "Stake already exists");
45+
require(!addresses[msg.sender].personalStake.exists, "Stake already exists");
3346

3447
require(
3548
stakingToken.transferFrom(msg.sender, this, _amount),
3649
"Stake required");
3750

38-
stakes[msg.sender] = Stake(block.number, _amount, true);
39-
amountStakedFor[msg.sender].add(_amount);
51+
addresses[msg.sender].personalStake = Stake(block.number, _amount, true);
52+
addresses[msg.sender].amountStakedFor.add(_amount);
4053

4154
emit Staked(
4255
msg.sender,
@@ -46,17 +59,17 @@ contract ERC900BasicStakeContainer is ERC900 {
4659
}
4760

4861
function stakeFor(address _user, uint256 _amount, bytes _data) public {
49-
require(!stakes[msg.sender].exists, "Stake already exists");
62+
require(!addresses[msg.sender].personalStake.exists, "Stake already exists");
5063

5164
require(
5265
stakingToken.transferFrom(msg.sender, this, _amount),
5366
"Stake required");
5467

55-
stakes[msg.sender] = Stake(block.number, _amount, true);
68+
addresses[msg.sender].personalStake = Stake(block.number, _amount, true);
5669

5770
// Notice here that we are increasing the staked amount for _user
5871
// instead of msg.sender
59-
amountStakedFor[_user].add(_amount);
72+
addresses[_user].amountStakedFor.add(_amount);
6073

6174
emit Staked(
6275
_user,
@@ -66,7 +79,7 @@ contract ERC900BasicStakeContainer is ERC900 {
6679
}
6780

6881
function unstake(uint256 _amount, bytes _data) public {
69-
require(stakes[msg.sender].exists, "Stake doesn't exist");
82+
require(addresses[msg.sender].personalStake.exists, "Stake doesn't exist");
7083

7184
// Transfer the staked tokens from this contract back tot he sender
7285
// Notice that we are using transfer instead of transferFrom here, so
@@ -77,11 +90,11 @@ contract ERC900BasicStakeContainer is ERC900 {
7790

7891
// If this was a complete withdrawal, then delete the previous stake to reset
7992
// the block number and exists flag
80-
if (stakes[msg.sender].amount == 0) {
81-
delete stakes[msg.sender];
82-
amountStakedFor[msg.sender] = 0;
93+
if (addresses[msg.sender].personalStake.amount == 0) {
94+
delete addresses[msg.sender].personalStake;
95+
addresses[msg.sender].amountStakedFor = 0;
8396
} else {
84-
amountStakedFor[msg.sender].sub(_amount);
97+
addresses[msg.sender].amountStakedFor.sub(_amount);
8598
}
8699

87100
emit Unstaked(
@@ -92,7 +105,7 @@ contract ERC900BasicStakeContainer is ERC900 {
92105
}
93106

94107
function totalStakedFor(address _address) public view returns (uint256) {
95-
return amountStakedFor[_address];
108+
return addresses[_address].amountStakedFor;
96109
}
97110

98111
function totalStaked() public view returns (uint256) {

contracts/ERC900/ERC900StakeContainer.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pragma solidity ^0.4.24;
22

33
import "./ERC900BasicStakeContainer.sol";
44

5+
56
/**
67
* @title ERC900StakeContainer
78
*/
@@ -10,11 +11,12 @@ contract ERC900StakeContainer is ERC900BasicStakeContainer {
1011
ERC900BasicStakeContainer(_stakingToken) {
1112
}
1213

13-
/*
14+
1415
function supportsHistory() public pure returns (bool) {
1516
return true;
1617
}
1718

19+
/*
1820
function lastStakedFor(address addr) public view returns (uint256) {
1921
2022
}

migrations/3_deploy_stakecontainer.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const CodexToken = artifacts.require('./CodexToken.sol')
2+
const ERC900StakeContainer = artifacts.require('./ERC900StakeContainer.sol')
3+
4+
module.exports = (deployer) => {
5+
deployer.deploy(ERC900StakeContainer, CodexToken.address)
6+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const CodexTitle = artifacts.require('./CodexTitle.sol')
22

3-
module.exports = (deployer, network, accounts) => {
3+
module.exports = (deployer) => {
44
deployer.deploy(CodexTitle)
55
}

migrations/4_deploy_proxy.js renamed to migrations/5_deploy_proxy.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ module.exports = async (deployer, network, accounts) => {
1515
})
1616
.catch((error) => {
1717
console.log(error)
18+
19+
throw error
1820
})
1921
}

migrations/5_initialize_721token.js renamed to migrations/6_initialize_721token.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,10 @@ const CodexTitle = artifacts.require('./CodexTitle.sol')
33
const CodexTitleProxy = artifacts.require('./CodexTitleProxy.sol')
44

55
module.exports = async (deployer, network, accounts) => {
6+
const proxiedCodexTitle = CodexTitle.at(CodexTitleProxy.address)
67

78
deployer
89
.then(async () => {
9-
const codexTitleProxy = await CodexTitleProxy.deployed()
10-
const proxiedCodexTitle = CodexTitle.at(codexTitleProxy.address)
11-
12-
return proxiedCodexTitle
13-
})
14-
.then(async (proxiedCodexTitle) => {
15-
1610
let initialFees
1711
let erc20TokenAddress
1812

@@ -38,10 +32,8 @@ module.exports = async (deployer, network, accounts) => {
3832

3933
console.log(`Setting the fees to ${initialFees} at ERC-20 token address: ${erc20TokenAddress}`)
4034
await proxiedCodexTitle.setFees(erc20TokenAddress, accounts[0], initialFees)
41-
42-
return proxiedCodexTitle
4335
})
44-
.then(async (proxiedCodexTitle) => {
36+
.then(async () => {
4537

4638
let tokenURIPrefix
4739

@@ -70,5 +62,7 @@ module.exports = async (deployer, network, accounts) => {
7062
})
7163
.catch((error) => {
7264
console.log(error)
65+
66+
throw error
7367
})
7468
}

migrations/6_transfer_ownership.js renamed to migrations/7_transfer_ownership.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,7 @@ module.exports = async (deployer, network, accounts) => {
5050
})
5151
.catch((error) => {
5252
console.error(error)
53+
54+
throw error
5355
})
5456
}

test/token/behaviors/CodexTitle.behavior.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import modifyMetadataHashesUnbound from '../../helpers/modifyMetadataHashes'
33

44
const { BigNumber } = web3
55
const CodexToken = artifacts.require('CodexToken.sol')
6-
const ERC900BasicStakeContainer = artifacts.require('ERC900BasicStakeContainer.sol')
6+
const ERC900StakeContainer = artifacts.require('ERC900StakeContainer.sol')
77

88
require('chai')
99
.use(require('chai-as-promised'))
@@ -148,7 +148,7 @@ export default function shouldBehaveLikeCodexTitle(accounts) {
148148
let stakeContainer
149149

150150
beforeEach(async function () {
151-
stakeContainer = await ERC900BasicStakeContainer.new(codexToken.address)
151+
stakeContainer = await ERC900StakeContainer.new(codexToken.address)
152152

153153
await this.token.setStakeContainer(stakeContainer.address)
154154

0 commit comments

Comments
 (0)