Skip to content

Commit

Permalink
Merge pull request #136 from livepeer/yf/eth-payments
Browse files Browse the repository at this point in the history
Use ETH for job deposits and fee payments
  • Loading branch information
yondonfu committed Jan 3, 2018
2 parents b5cd4f3 + ad4059c commit a313fa6
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 155 deletions.
91 changes: 45 additions & 46 deletions contracts/bonding/BondingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
// Represents a delegator's current state
struct Delegator {
uint256 bondedAmount; // The amount of bonded tokens
uint256 unbondedAmount; // The amount of unbonded tokens
uint256 fees; // The amount of fees collected
address delegateAddress; // The address delegated to
uint256 delegatedAmount; // The amount of tokens delegated to the delegator
uint256 startRound; // The round the delegator transitions to bonded phase and is delegated to someone
Expand Down Expand Up @@ -279,19 +279,8 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
}

if (_amount > 0) {
if (_amount > del.unbondedAmount) {
// If amount to bond is greater than the delegator's unbonded amount
// use the delegator's unbonded amount and transfer the rest from the sender
uint256 transferAmount = _amount.sub(del.unbondedAmount);
// Set unbonded amount to 0
del.unbondedAmount = 0;
// Transfer the token to the Minter
livepeerToken().transferFrom(msg.sender, minter(), transferAmount);
} else {
// If the amount to bond is less than or equal to the delegator's unbonded amount
// just use the delegator's unbonded amount
del.unbondedAmount = del.unbondedAmount.sub(_amount);
}
// Transfer the LPT to the Minter
livepeerToken().transferFrom(msg.sender, minter(), _amount);
}

Bond(_to, msg.sender);
Expand Down Expand Up @@ -336,35 +325,46 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
}

/**
* @dev Withdraws withdrawable funds back to the caller after unbonding period.
* @dev Withdraws bonded stake to the caller after unbonding period.
*/
function withdraw()
function withdrawStake()
external
whenSystemNotPaused
currentRoundInitialized
autoClaimTokenPoolsShares
{
// Delegator must either have unbonded tokens or be in the unbonded state
require(delegators[msg.sender].unbondedAmount > 0 || delegatorStatus(msg.sender) == DelegatorStatus.Unbonded);
// Delegator must be in the unbonded state
require(delegatorStatus(msg.sender) == DelegatorStatus.Unbonded);

uint256 amount = 0;
uint256 amount = delegators[msg.sender].bondedAmount;
delegators[msg.sender].bondedAmount = 0;
delegators[msg.sender].withdrawRound = 0;

if (delegators[msg.sender].unbondedAmount > 0) {
// Withdraw unbonded amount
amount = amount.add(delegators[msg.sender].unbondedAmount);
delegators[msg.sender].unbondedAmount = 0;
}
// Tell Minter to transfer stake (LPT) to the delegator
minter().transferTokens(msg.sender, amount);

if (delegatorStatus(msg.sender) == DelegatorStatus.Unbonded) {
// Withdraw bonded amount which is now unbonded
amount = amount.add(delegators[msg.sender].bondedAmount);
delegators[msg.sender].bondedAmount = 0;
delegators[msg.sender].withdrawRound = 0;
}
WithdrawStake(msg.sender);
}

minter().transferTokens(msg.sender, amount);
/**
* @dev Withdraws fees to the caller
*/
function withdrawFees()
external
whenSystemNotPaused
currentRoundInitialized
autoClaimTokenPoolsShares
{
// Delegator must have fees
require(delegators[msg.sender].fees > 0);

uint256 amount = delegators[msg.sender].fees;
delegators[msg.sender].fees = 0;

Withdraw(msg.sender);
// Tell Minter to transfer fees (ETH) to the delegator
minter().withdrawETH(msg.sender, amount);

WithdrawFees(msg.sender);
}

/*
Expand Down Expand Up @@ -575,10 +575,10 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
}

/*
* @dev Returns bonded stake for a delegator. Includes reward pool shares since lastClaimTokenPoolsSharesRound
* @dev Returns pending bonded stake for a delegator. Includes reward pool shares since lastClaimTokenPoolsSharesRound
* @param _delegator Address of delegator
*/
function delegatorStake(address _delegator) public view returns (uint256) {
function pendingStake(address _delegator) public view returns (uint256) {
Delegator storage del = delegators[_delegator];

// Add rewards from the rounds during which the delegator was bonded to a transcoder
Expand All @@ -603,16 +603,16 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
}

/*
* @dev Returns unbonded amount for a delegator. Includes fee pool shares since lastClaimTokenPoolsSharesRound
* @dev Returns pending fees for a delegator. Includes fee pool shares since lastClaimTokenPoolsSharesRound
* @param _delegator Address of delegator
*/
function delegatorUnbondedAmount(address _delegator) public view returns (uint256) {
function pendingFees(address _delegator) public view returns (uint256) {
Delegator storage del = delegators[_delegator];

// Add fees from the rounds during which the delegator was bonded to a transcoder
if (delegatorStatus(_delegator) == DelegatorStatus.Bonded && transcoderStatus(del.delegateAddress) == TranscoderStatus.Registered) {
uint256 currentRound = roundsManager().currentRound();
uint256 currentUnbondedAmount = del.unbondedAmount;
uint256 currentFees = del.fees;
uint256 currentBondedAmount = del.bondedAmount;

for (uint256 i = del.lastClaimTokenPoolsSharesRound + 1; i <= currentRound; i++) {
Expand All @@ -621,16 +621,16 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
if (tokenPools.hasClaimableShares()) {
bool isTranscoder = _delegator == del.delegateAddress;
// Calculate and add fee pool share from this round
currentUnbondedAmount = currentUnbondedAmount.add(tokenPools.feePoolShare(currentBondedAmount, isTranscoder));
currentFees = currentFees.add(tokenPools.feePoolShare(currentBondedAmount, isTranscoder));
// Calculate new bonded amount with rewards from this round. Updated bonded amount used
// to calculate fee pool share in next round
currentBondedAmount = currentBondedAmount.add(tokenPools.rewardPoolShare(currentBondedAmount, isTranscoder));
}
}

return currentUnbondedAmount;
return currentFees;
} else {
return del.unbondedAmount;
return del.fees;
}
}

Expand Down Expand Up @@ -743,12 +743,12 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {
)
public
view
returns (uint256 bondedAmount, uint256 unbondedAmount, address delegateAddress, uint256 delegatedAmount, uint256 startRound, uint256 withdrawRound, uint256 lastClaimTokenPoolsSharesRound)
returns (uint256 bondedAmount, uint256 fees, address delegateAddress, uint256 delegatedAmount, uint256 startRound, uint256 withdrawRound, uint256 lastClaimTokenPoolsSharesRound)
{
Delegator storage del = delegators[_delegator];

bondedAmount = del.bondedAmount;
unbondedAmount = del.unbondedAmount;
fees = del.fees;
delegateAddress = del.delegateAddress;
delegatedAmount = del.delegatedAmount;
startRound = del.startRound;
Expand Down Expand Up @@ -834,26 +834,25 @@ contract BondingManager is ManagerProxyTarget, IBondingManager {

if (del.lastClaimTokenPoolsSharesRound > 0) {
uint256 currentBondedAmount = del.bondedAmount;
uint256 currentUnbondedAmount = del.unbondedAmount;
uint256 currentFees = del.fees;

for (uint256 i = del.lastClaimTokenPoolsSharesRound + 1; i <= _endRound; i++) {
TokenPools.Data storage tokenPools = transcoders[del.delegateAddress].tokenPoolsPerRound[i];


if (tokenPools.hasClaimableShares()) {
bool isTranscoder = _delegator == del.delegateAddress;

var (fees, rewards) = tokenPools.claimShare(currentBondedAmount, isTranscoder);

currentUnbondedAmount = currentUnbondedAmount.add(fees);
currentFees = currentFees.add(fees);
currentBondedAmount = currentBondedAmount.add(rewards);
}
}

// Rewards are bonded by default
del.bondedAmount = currentBondedAmount;
// Fees are unbonded by default
del.unbondedAmount = currentUnbondedAmount;
del.fees = currentFees;
}

del.lastClaimTokenPoolsSharesRound = _endRound;
Expand Down
3 changes: 2 additions & 1 deletion contracts/bonding/IBondingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ contract IBondingManager {
event Reward(address indexed transcoder, uint256 amount);
event Bond(address indexed delegate, address indexed delegator);
event Unbond(address indexed delegate, address indexed delegator);
event Withdraw(address indexed delegator);
event WithdrawStake(address indexed delegator);
event WithdrawFees(address indexed delegator);

// External functions
function setActiveTranscoders() external;
Expand Down
15 changes: 7 additions & 8 deletions contracts/jobs/JobsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,14 @@ contract JobsManager is ManagerProxyTarget, IVerifiable, IJobsManager {
}

/*
* @dev Deposit funds for jobs
* @param _amount Amount to deposit
* @dev Deposit ETH for jobs
*/
function deposit(uint256 _amount) external whenSystemNotPaused {
broadcasters[msg.sender].deposit = broadcasters[msg.sender].deposit.add(_amount);
// Transfer tokens for deposit to Minter. Sender needs to approve amount first
livepeerToken().transferFrom(msg.sender, minter(), _amount);
function deposit() external payable whenSystemNotPaused {
broadcasters[msg.sender].deposit = broadcasters[msg.sender].deposit.add(msg.value);
// Transfer ETH for deposit to Minter
minter().depositETH.value(msg.value)();

Deposit(msg.sender, _amount);
Deposit(msg.sender, msg.value);
}

/*
Expand All @@ -253,7 +252,7 @@ contract JobsManager is ManagerProxyTarget, IVerifiable, IJobsManager {

uint256 amount = broadcasters[msg.sender].deposit;
delete broadcasters[msg.sender];
minter().transferTokens(msg.sender, amount);
minter().withdrawETH(msg.sender, amount);

Withdraw(msg.sender);
}
Expand Down
8 changes: 6 additions & 2 deletions contracts/test/BondingManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ contract BondingManagerMock is IBondingManager {
withdrawAmount = _amount;
}

function withdraw() external {
minter.transferTokens(msg.sender, withdrawAmount);
function withdraw(bool _unbonded, address _recipient) external {
if (_unbonded) {
minter.withdrawETH(_recipient, withdrawAmount);
} else {
minter.transferTokens(_recipient, withdrawAmount);
}
}

function reward() external {
Expand Down
12 changes: 10 additions & 2 deletions contracts/test/JobsManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,16 @@ contract JobsManagerMock is IJobsManager {
return bondingManager.slashTranscoder(transcoder, finder, slashAmount, finderFee);
}

function withdraw() external {
minter.transferTokens(msg.sender, withdrawAmount);
function deposit() external payable {
minter.depositETH.value(msg.value)();
}

function withdraw(bool _unbonded, address _recipient) external {
if (_unbonded) {
minter.withdrawETH(_recipient, withdrawAmount);
} else {
minter.transferTokens(_recipient, withdrawAmount);
}
}

function callVerify() external payable {
Expand Down
6 changes: 6 additions & 0 deletions contracts/test/MinterMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ contract MinterMock is IMinter {

function burnTokens(uint256 _amount) external {}

function withdrawETH(address _to, uint256 _amount) external {}

function depositETH() external payable returns (bool) {
return true;
}

function addToRedistributionPool(uint256 _amount) external {}

function setCurrentRewardTokens() external {}
Expand Down
2 changes: 2 additions & 0 deletions contracts/token/IMinter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ contract IMinter {
function createReward(uint256 _fracNum, uint256 _fracDenom) external returns (uint256);
function transferTokens(address _to, uint256 _amount) external;
function burnTokens(uint256 _amount) external;
function depositETH() external payable returns (bool);
function withdrawETH(address _to, uint256 _amount) external;
function setCurrentRewardTokens() external;
}
16 changes: 16 additions & 0 deletions contracts/token/Minter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ contract Minter is Manager, IMinter {
livepeerToken().burn(_amount);
}

/*
* @dev Withdraw ETH to a recipient
* @param _to Recipient address
* @param _amount Amount of ETH
*/
function withdrawETH(address _to, uint256 _amount) external onlyBondingManagerOrJobsManager whenSystemNotPaused {
_to.transfer(_amount);
}

/*
* @dev Deposit ETH from the JobsManager
*/
function depositETH() external payable onlyJobsManager whenSystemNotPaused returns (bool) {
return true;
}

/*
* @dev Set the reward token amounts for the round. Only callable by the RoundsManager
*/
Expand Down

0 comments on commit a313fa6

Please sign in to comment.