@@ -16,6 +16,8 @@ pragma solidity 0.5.17;
1616
1717import "@keep-network/keep-core/contracts/KeepRegistry.sol " ;
1818import "@keep-network/keep-core/contracts/TokenStaking.sol " ;
19+ import "@keep-network/keep-core/contracts/TokenGrant.sol " ;
20+ import "@keep-network/keep-core/contracts/libraries/RolesLookup.sol " ;
1921
2022import "openzeppelin-solidity/contracts/math/SafeMath.sol " ;
2123
@@ -24,13 +26,17 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol";
2426/// @notice Contract holding deposits from keeps' operators.
2527contract KeepBonding {
2628 using SafeMath for uint256 ;
29+ using RolesLookup for address payable ;
2730
2831 // Registry contract with a list of approved factories (operator contracts).
2932 KeepRegistry internal registry;
3033
3134 // KEEP token staking contract.
3235 TokenStaking internal tokenStaking;
3336
37+ // KEEP token grant contract.
38+ TokenGrant internal tokenGrant;
39+
3440 // Unassigned value in wei deposited by operators.
3541 mapping (address => uint256 ) public unbondedValue;
3642
@@ -71,10 +77,16 @@ contract KeepBonding {
7177
7278 /// @notice Initializes Keep Bonding contract.
7379 /// @param registryAddress Keep registry contract address.
74- /// @param tokenStakingAddress KEEP Token staking contract address.
75- constructor (address registryAddress , address tokenStakingAddress ) public {
80+ /// @param tokenStakingAddress KEEP token staking contract address.
81+ /// @param tokenGrantAddress KEEP token grant contract address.
82+ constructor (
83+ address registryAddress ,
84+ address tokenStakingAddress ,
85+ address tokenGrantAddress
86+ ) public {
7687 registry = KeepRegistry (registryAddress);
7788 tokenStaking = TokenStaking (tokenStakingAddress);
89+ tokenGrant = TokenGrant (tokenGrantAddress);
7890 }
7991
8092 /// @notice Add the provided value to operator's pool available for bonding.
@@ -113,34 +125,47 @@ contract KeepBonding {
113125 }
114126
115127 /// @notice Withdraws amount from operator's value available for bonding.
116- /// Can be called only by the operator or by the stake owner. The value is
117- /// transferred to the beneficiary associated with the operator.
128+ /// Should not be used by grantee of managed grants. For this case,
129+ /// please use `withdrawAsManagedGrantee`.
130+ ///
131+ /// This function can be called only by:
132+ /// - operator,
133+ /// - liquid, staked tokens owner (not a grant),
134+ /// - direct staked tokens grantee (not a managed grant).
135+ ///
118136 /// @param amount Value to withdraw in wei.
119137 /// @param operator Address of the operator.
120138 function withdraw (uint256 amount , address operator ) public {
121139 require (
122140 msg .sender == operator ||
123- msg .sender == tokenStaking.ownerOf (operator),
141+ msg .sender .isTokenOwnerForOperator (operator, tokenStaking) ||
142+ msg .sender .isGranteeForOperator (operator, tokenGrant),
124143 "Only operator or the owner is allowed to withdraw bond "
125144 );
126145
127- require (
128- unbondedValue[operator] >= amount,
129- "Insufficient unbonded value "
130- );
131-
132- unbondedValue[operator] = unbondedValue[operator].sub (amount);
146+ withdrawBond (amount, operator);
147+ }
133148
134- address beneficiary = tokenStaking.beneficiaryOf (operator);
149+ /// @notice Withdraws amount from operator's value available for bonding.
150+ /// Can be called only by staked tokens managed grantee.
151+ /// @param amount Value to withdraw in wei.
152+ /// @param operator Address of the operator.
153+ /// @param managedGrant Address of the managed grant contract.
154+ function withdrawAsManagedGrantee (
155+ uint256 amount ,
156+ address operator ,
157+ address managedGrant
158+ ) public {
135159 require (
136- beneficiary != address (0 ),
137- "Beneficiary not defined for the operator "
160+ msg .sender .isManagedGranteeForOperator (
161+ operator,
162+ managedGrant,
163+ tokenGrant
164+ ),
165+ "Only grantee is allowed to withdraw bond "
138166 );
139167
140- (bool success , ) = beneficiary.call.value (amount)("" );
141- require (success, "Transfer failed " );
142-
143- emit UnbondedValueWithdrawn (operator, beneficiary, amount);
168+ withdrawBond (amount, operator);
144169 }
145170
146171 /// @notice Create bond for the given operator, holder, reference and amount.
@@ -338,4 +363,27 @@ contract KeepBonding {
338363 {
339364 return authorizedPools[_operator][_poolAddress];
340365 }
366+
367+ /// @notice Withdraws the provided amount from unbonded value of the
368+ /// provided operator to operator's beneficiary. If there is no enough
369+ /// unbonded value or the transfer failed, function fails.
370+ function withdrawBond (uint256 amount , address operator ) internal {
371+ require (
372+ unbondedValue[operator] >= amount,
373+ "Insufficient unbonded value "
374+ );
375+
376+ unbondedValue[operator] = unbondedValue[operator].sub (amount);
377+
378+ address beneficiary = tokenStaking.beneficiaryOf (operator);
379+ require (
380+ beneficiary != address (0 ),
381+ "Beneficiary not defined for the operator "
382+ );
383+
384+ (bool success , ) = beneficiary.call.value (amount)("" );
385+ require (success, "Transfer failed " );
386+
387+ emit UnbondedValueWithdrawn (operator, beneficiary, amount);
388+ }
341389}
0 commit comments