Skip to content

Commit

Permalink
Remove pendingBalance in TokenLocking
Browse files Browse the repository at this point in the history
  • Loading branch information
kronosapiens authored and area committed Feb 11, 2021
1 parent 2d19c40 commit 12eb33d
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 162 deletions.
7 changes: 4 additions & 3 deletions contracts/colonyNetwork/ColonyNetworkMining.sol
Expand Up @@ -217,7 +217,8 @@ contract ColonyNetworkMining is ColonyNetworkStorage, MultiChain {
address clnyToken = IMetaColony(metaColony).getToken();
uint256 amount = pendingMiningRewards[_recipient];
pendingMiningRewards[_recipient] = 0;
ITokenLocking(tokenLocking).transfer(clnyToken, amount, _recipient, true);
ERC20Extended(clnyToken).approve(tokenLocking, amount);
ITokenLocking(tokenLocking).depositFor(clnyToken, amount, _recipient);
}

function stakeForMining(uint256 _amount) public stoppable {
Expand All @@ -244,8 +245,8 @@ contract ColonyNetworkMining is ColonyNetworkStorage, MultiChain {
}

function burnUnneededRewards(uint256 _amount) public stoppable onlyReputationMiningCycle() {
ITokenLocking(tokenLocking).claim(IMetaColony(metaColony).getToken(), true);
ITokenLocking(tokenLocking).burn(_amount);
address clnyToken = IMetaColony(metaColony).getToken();
ERC20Extended(clnyToken).burn(_amount);
}

function setReputationMiningCycleReward(uint256 _amount) public stoppable
Expand Down
5 changes: 4 additions & 1 deletion contracts/extensions/VotingReputation.sol
Expand Up @@ -315,7 +315,9 @@ contract VotingReputation is ColonyExtension, PatriciaTreeProofs {

colony.obligateStake(msg.sender, motion.domainId, amount);
colony.transferStake(_permissionDomainId, _childSkillIndex, address(this), msg.sender, motion.domainId, amount, address(this));
tokenLocking.claim(token, true);

ERC20Extended(token).approve(address(tokenLocking), amount);
tokenLocking.deposit(token, amount, true);

// Update the stake
motion.stakes[_vote] = add(motion.stakes[_vote], amount);
Expand Down Expand Up @@ -445,6 +447,7 @@ contract VotingReputation is ColonyExtension, PatriciaTreeProofs {

emit MotionEventSet(_motionId, REVEAL_END);
}

tokenLocking.transfer(token, voterReward, msg.sender, true);
}

Expand Down
19 changes: 8 additions & 11 deletions contracts/tokenLocking/ITokenLocking.sol
Expand Up @@ -49,23 +49,25 @@ interface ITokenLocking is TokenLockingDataTypes {
/// @param _lockId Id of the lock user wants to increment to
function incrementLockCounterTo(address _token, uint256 _lockId) external;

/// @notice Deposit `_amount` of colony tokens. Goes into pendingBalance if token is locked.
/// @notice DEPRECATED Deposit `_amount` of deposited tokens. Can only be called if user tokens are not locked.
/// Before calling this function user has to allow that their tokens can be transferred by token locking contract.
/// @param _token Address of the token to deposit
/// @param _amount Amount to deposit
function deposit(address _token, uint256 _amount) external;

/// @notice Deposit `_amount` of colony tokens.
/// Before calling this function user has to allow that their tokens can be transferred by token locking contract.
/// @param _token Address of the token to deposit
/// @param _amount Amount to deposit
/// @param _force Pass true to forcibly unlock the token
function deposit(address _token, uint256 _amount, bool _force) external;

/// @notice Deposit `_amount` of colony tokens in the recipient's account. Goes into pendingBalance if token is locked.
/// @param _token Address of the token to deposit
/// @param _amount Amount to deposit
/// @param _recipient User to receive the tokens
function depositFor(address _token, uint256 _amount, address _recipient) external;

/// @notice Claim any pending tokens. Can only be called if user tokens are not locked.
/// @param _token Address of the token to withdraw from
/// @param _force Pass true to forcibly unlock the token
function claim(address _token, bool _force) external;

/// @notice Transfer tokens to a recipient's pending balance. Can only be called if user tokens are not locked.
/// @param _token Address of the token to transfer
/// @param _amount Amount to transfer
Expand All @@ -90,11 +92,6 @@ interface ITokenLocking is TokenLockingDataTypes {
/// @dev It's a NOOP. You don't need to call this, and if you write a contract that does it will break in the future.
function reward(address _recipient, uint256 _amount) external;

/// @notice Function called to burn CLNY tokens held by TokenLocking.
/// @dev While external, it can only be called successfully by colonyNetwork and is only used for reputation mining.
/// @param _amount Amount of CLNY to burn
function burn(uint256 _amount) external;

/// @notice Allow the colony to obligate some amount of tokens as a stake.
/// @dev Can only be called by a colony or colonyNetwork
/// @param _user Address of the user that is allowing their holdings to be staked by the caller
Expand Down
39 changes: 18 additions & 21 deletions contracts/tokenLocking/TokenLocking.sol
Expand Up @@ -95,12 +95,23 @@ contract TokenLocking is TokenLockingStorage, DSMath { // ignore-swc-123
userLocks[_token][msg.sender].lockCount = _lockId;
}

// Deprecated interface
function deposit(address _token, uint256 _amount) public {
require(ERC20Extended(_token).transferFrom(msg.sender, address(this), _amount), "colony-token-locking-transfer-failed"); // ignore-swc-123
deposit(_token, _amount, false);
}

makeConditionalDeposit(_token, _amount, msg.sender);
function deposit(address _token, uint256 _amount, bool _force) public tokenNotLocked(_token, _force) {
require(ERC20Extended(_token).transferFrom(msg.sender, address(this), _amount), "colony-token-locking-transfer-failed"); // ignore-swc-123

Lock storage lock = userLocks[_token][msg.sender];
lock.balance = add(lock.balance, _amount);

// Handle the pendingBalance, if any (idempotent operation)
if (_force) {
lock.balance = add(lock.balance, lock.pendingBalance);
delete lock.pendingBalance;
}

emit UserTokenDeposited(_token, msg.sender, lock.balance);
}

Expand All @@ -113,22 +124,13 @@ contract TokenLocking is TokenLockingStorage, DSMath { // ignore-swc-123
emit UserTokenDeposited(_token, _recipient, lock.balance);
}

function claim(address _token, bool _force) public
tokenNotLocked(_token, _force)
{
Lock storage lock = userLocks[_token][msg.sender];
lock.balance = add(lock.balance, lock.pendingBalance);
lock.pendingBalance = 0;

emit UserTokenClaimed(_token, msg.sender, lock.balance);
}

function transfer(address _token, uint256 _amount, address _recipient, bool _force) public
notObligated(_token, _amount)
tokenNotLocked(_token, _force)
{
Lock storage userLock = userLocks[_token][msg.sender];
userLock.balance = sub(userLock.balance, _amount);

makeConditionalDeposit(_token, _amount, _recipient);

emit UserTokenTransferred(_token, msg.sender, _recipient, _amount);
Expand Down Expand Up @@ -175,19 +177,14 @@ contract TokenLocking is TokenLockingStorage, DSMath { // ignore-swc-123
// Transfer the the tokens
Lock storage userLock = userLocks[_token][_user];
userLock.balance = sub(userLock.balance, _amount);
makeConditionalDeposit(_token, _amount, _recipient);

require(ERC20Extended(_token).transfer(_recipient, _amount), "colony-token-locking-transfer-failed");
}

function reward(address _recipient, uint256 _amount) public pure { // solhint-disable-line no-empty-blocks

}

function burn(uint256 _amount) public {
require(msg.sender==colonyNetwork, "colony-token-locking-not-colony-network");
address clnyToken = IMetaColony(IColonyNetwork(colonyNetwork).getMetaColony()).getToken();
ERC20Extended(clnyToken).burn(_amount);
}

function getTotalLockCount(address _token) public view returns (uint256) {
return totalLockCount[_token];
}
Expand All @@ -211,11 +208,11 @@ contract TokenLocking is TokenLockingStorage, DSMath { // ignore-swc-123
// Internal functions

function makeConditionalDeposit(address _token, uint256 _amount, address _user) internal {
Lock storage userLock = userLocks[_token][_user];
if (isTokenUnlocked(_token, _user)) {
Lock storage userLock = userLocks[_token][_user];
userLock.balance = add(userLock.balance, _amount);
} else {
userLock.pendingBalance = add(userLock.pendingBalance, _amount);
require(ERC20Extended(_token).transfer(_user, _amount), "colony-token-locking-transfer-failed");
}
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/tokenLocking/TokenLockingDataTypes.sol
Expand Up @@ -35,7 +35,7 @@ interface TokenLockingDataTypes {
uint256 balance;
// Weighted average of deposit timestamps (no longer used)
uint256 DEPRECATED_timestamp; // solhint-disable-line var-name-mixedcase
// Pending balance, can claim once unlocked
uint256 pendingBalance;
// Pending balance, can claim once unlocked (no longer used)
uint256 DEPRECATED_pendingBalance;
}
}
34 changes: 11 additions & 23 deletions docs/_Interface_ITokenLocking.md
Expand Up @@ -22,49 +22,36 @@ Allow the colony to obligate some amount of tokens as a stake.
|_token|address|The colony's internal token address


### `burn`

Function called to burn CLNY tokens held by TokenLocking.

*Note: While external, it can only be called successfully by colonyNetwork and is only used for reputation mining.*

**Parameters**

|Name|Type|Description|
|---|---|---|
|_amount|uint256|Amount of CLNY to burn


### `claim`
### `deobligateStake`

Claim any pending tokens. Can only be called if user tokens are not locked.
Deobligate the user some amount of tokens, releasing the stake. Can only be called by a colony or colonyNetwork.


**Parameters**

|Name|Type|Description|
|---|---|---|
|_token|address|Address of the token to withdraw from
|_force|bool|Pass true to forcibly unlock the token
|_user|address|Address of the account we are deobligating.
|_amount|uint256|Amount of colony's internal token we are deobligating.
|_token|address|The colony's internal token address


### `deobligateStake`
### `deposit`

Deobligate the user some amount of tokens, releasing the stake. Can only be called by a colony or colonyNetwork.
DEPRECATED Deposit `_amount` of deposited tokens. Can only be called if user tokens are not locked. Before calling this function user has to allow that their tokens can be transferred by token locking contract.


**Parameters**

|Name|Type|Description|
|---|---|---|
|_user|address|Address of the account we are deobligating.
|_amount|uint256|Amount of colony's internal token we are deobligating.
|_token|address|The colony's internal token address
|_token|address|Address of the token to deposit
|_amount|uint256|Amount to deposit


### `deposit`

Deposit `_amount` of colony tokens. Goes into pendingBalance if token is locked. Before calling this function user has to allow that their tokens can be transferred by token locking contract.
Deposit `_amount` of colony tokens. Before calling this function user has to allow that their tokens can be transferred by token locking contract.


**Parameters**
Expand All @@ -73,6 +60,7 @@ Deposit `_amount` of colony tokens. Goes into pendingBalance if token is locked.
|---|---|---|
|_token|address|Address of the token to deposit
|_amount|uint256|Amount to deposit
|_force|bool|Pass true to forcibly unlock the token


### `depositFor`
Expand Down
2 changes: 1 addition & 1 deletion helpers/test-data-generator.js
Expand Up @@ -261,7 +261,7 @@ export async function giveUserCLNYTokensAndStake(colonyNetwork, user, _amount) {
const tokenLockingAddress = await colonyNetwork.getTokenLocking();
const tokenLocking = await ITokenLocking.at(tokenLockingAddress);
await clnyToken.approve(tokenLocking.address, amount, { from: user });
await tokenLocking.deposit(clnyToken.address, amount, { from: user });
await tokenLocking.methods["deposit(address,uint256,bool)"](clnyToken.address, amount, true, { from: user });
await colonyNetwork.stakeForMining(amount, { from: user });
}

Expand Down
2 changes: 1 addition & 1 deletion migrations/8_setup_meta_colony.js
Expand Up @@ -50,7 +50,7 @@ module.exports = async function (deployer, network, accounts) {
const mainAccountBalance = await clnyToken.balanceOf(MAIN_ACCOUNT);
assert.equal(mainAccountBalance.toString(), DEFAULT_STAKE.toString());
const tokenLocking = await ITokenLocking.at(tokenLockingAddress);
await tokenLocking.deposit(clnyToken.address, DEFAULT_STAKE, { from: MAIN_ACCOUNT });
await tokenLocking.methods["deposit(address,uint256,bool)"](clnyToken.address, DEFAULT_STAKE, true, { from: MAIN_ACCOUNT });
await colonyNetwork.stakeForMining(DEFAULT_STAKE, { from: MAIN_ACCOUNT });
await metaColony.addGlobalSkill();

Expand Down
2 changes: 1 addition & 1 deletion test-gas-costs/gasCosts.js
Expand Up @@ -312,7 +312,7 @@ contract("All", function (accounts) {
const userReputationProof = [key, value, branchMask, siblings];

await newToken.approve(tokenLocking.address, workerReputation, { from: WORKER });
await tokenLocking.deposit(newToken.address, workerReputation, { from: WORKER });
await tokenLocking.methods["deposit(address,uint256,bool)"](newToken.address, workerReputation, true, { from: WORKER });
await forwardTime(1, this);

await fundColonyWithTokens(newColony, otherToken, 300);
Expand Down
2 changes: 2 additions & 0 deletions test/contracts-network/colony-network-extensions.js
Expand Up @@ -171,8 +171,10 @@ contract("Colony Network Extensions", (accounts) => {

const identifier = await extension.identifier();
const version = await extension.version();
const colonyAddress = await extension.getColony();
expect(identifier).to.equal(TEST_EXTENSION);
expect(version).to.eq.BN(2);
expect(colonyAddress).to.equal(colony.address);

// Only colonyNetwork can install the extension
await checkErrorRevert(extension.install(colony.address), "ds-auth-unauthorized");
Expand Down
17 changes: 8 additions & 9 deletions test/contracts-network/colony-reward-payouts.js
Expand Up @@ -85,7 +85,7 @@ contract("Colony Reward Payouts", (accounts) => {
await colony.bootstrapColony([userAddress1], [userReputation]);

await token.approve(tokenLocking.address, userTokens, { from: userAddress1 });
await tokenLocking.deposit(token.address, userTokens, { from: userAddress1 });
await tokenLocking.methods["deposit(address,uint256,bool)"](token.address, userTokens, true, { from: userAddress1 });

const userReputationSqrt = bnSqrt(userReputation);
const userTokensSqrt = bnSqrt(userTokens);
Expand Down Expand Up @@ -468,7 +468,7 @@ contract("Colony Reward Payouts", (accounts) => {

await token.transfer(userAddress3, userTokens3, { from: userAddress1 });
await token.approve(tokenLocking.address, userTokens3, { from: userAddress3 });
await tokenLocking.deposit(token.address, userTokens3, { from: userAddress3 });
await tokenLocking.methods["deposit(address,uint256,bool)"](token.address, userTokens3, true, { from: userAddress3 });
await forwardTime(1, this);

const { logs } = await colony.startNextRewardPayout(otherToken.address, ...colonyWideReputationProof);
Expand Down Expand Up @@ -621,8 +621,7 @@ contract("Colony Reward Payouts", (accounts) => {
const payoutId = logs[0].args.rewardPayoutId;

await token.approve(tokenLocking.address, userTokens, { from: userAddress1 });
await tokenLocking.deposit(token.address, userTokens, { from: userAddress1 });
await tokenLocking.claim(token.address, true, { from: userAddress1 });
await tokenLocking.methods["deposit(address,uint256,bool)"](token.address, userTokens, true, { from: userAddress1 });

await checkErrorRevert(
colony.claimRewardPayout(payoutId, initialSquareRoots, ...userReputationProof1, { from: userAddress1 }),
Expand Down Expand Up @@ -689,7 +688,7 @@ contract("Colony Reward Payouts", (accounts) => {

// This will allow token locking contract to sent tokens on users behalf
await newToken.approve(tokenLocking.address, userReputation, { from: userAddress1 });
await tokenLocking.deposit(newToken.address, userReputation, { from: userAddress1 });
await tokenLocking.methods["deposit(address,uint256,bool)"](newToken.address, userReputation, true, { from: userAddress1 });
await forwardTime(1, this);

({ logs } = await colony1.startNextRewardPayout(otherToken.address, ...colonyWideReputationProof1));
Expand Down Expand Up @@ -789,7 +788,7 @@ contract("Colony Reward Payouts", (accounts) => {

// This will allow token locking contract to sent tokens on users behalf
await newToken.approve(tokenLocking.address, userReputation, { from: userAddress1 });
await tokenLocking.deposit(newToken.address, userReputation, { from: userAddress1 });
await tokenLocking.methods["deposit(address,uint256,bool)"](newToken.address, userReputation, true, { from: userAddress1 });

await colony1.moveFundsBetweenPots(1, UINT256_MAX, UINT256_MAX, 1, 0, 100, otherToken.address);
await colony2.moveFundsBetweenPots(1, UINT256_MAX, UINT256_MAX, 1, 0, 100, otherToken.address);
Expand Down Expand Up @@ -891,9 +890,9 @@ contract("Colony Reward Payouts", (accounts) => {
await newToken.approve(tokenLocking.address, tokensPerUser, { from: userAddress3 });

// Send tokens to token locking contract.
await tokenLocking.deposit(newToken.address, tokensPerUser, { from: userAddress1 });
await tokenLocking.deposit(newToken.address, tokensPerUser, { from: userAddress2 });
await tokenLocking.deposit(newToken.address, tokensPerUser, { from: userAddress3 });
await tokenLocking.methods["deposit(address,uint256,bool)"](newToken.address, tokensPerUser, true, { from: userAddress1 });
await tokenLocking.methods["deposit(address,uint256,bool)"](newToken.address, tokensPerUser, true, { from: userAddress2 });
await tokenLocking.methods["deposit(address,uint256,bool)"](newToken.address, tokensPerUser, true, { from: userAddress3 });
await forwardTime(1, this);

await newColony.moveFundsBetweenPots(1, UINT256_MAX, UINT256_MAX, 1, 0, 100, payoutToken.address);
Expand Down
8 changes: 4 additions & 4 deletions test/contracts-network/colony-staking.js
Expand Up @@ -54,8 +54,8 @@ contract("Colony Staking", (accounts) => {
await token.approve(tokenLockingAddress, DEPOSIT, { from: USER1 });

tokenLocking = await ITokenLocking.at(tokenLockingAddress);
await tokenLocking.deposit(token.address, DEPOSIT, { from: USER0 });
await tokenLocking.deposit(token.address, DEPOSIT, { from: USER1 });
await tokenLocking.methods["deposit(address,uint256,bool)"](token.address, DEPOSIT, true, { from: USER0 });
await tokenLocking.methods["deposit(address,uint256,bool)"](token.address, DEPOSIT, true, { from: USER1 });
});

describe("when managing stakes", () => {
Expand Down Expand Up @@ -219,8 +219,8 @@ contract("Colony Staking", (accounts) => {
await colony.obligateStake(USER1, 1, WAD, { from: USER0 });
await colony.transferStake(1, UINT256_MAX, USER0, USER1, 1, WAD, USER2, { from: USER2 });

const deposit = await tokenLocking.getUserLock(token.address, USER2);
expect(deposit.balance).to.eq.BN(WAD);
const balance = await token.balanceOf(USER2);
expect(balance).to.eq.BN(WAD);
});
});
});

0 comments on commit 12eb33d

Please sign in to comment.