@@ -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
@@ -67,10 +73,16 @@ contract KeepBonding {
6773
6874 /// @notice Initializes Keep Bonding contract.
6975 /// @param registryAddress Keep registry contract address.
70- /// @param tokenStakingAddress KEEP Token staking contract address.
71- constructor (address registryAddress , address tokenStakingAddress ) public {
76+ /// @param tokenStakingAddress KEEP token staking contract address.
77+ /// @param tokenGrantAddress KEEP token grant contract address.
78+ constructor (
79+ address registryAddress ,
80+ address tokenStakingAddress ,
81+ address tokenGrantAddress
82+ ) public {
7283 registry = KeepRegistry (registryAddress);
7384 tokenStaking = TokenStaking (tokenStakingAddress);
85+ tokenGrant = TokenGrant (tokenGrantAddress);
7486 }
7587
7688 /// @notice Add the provided value to operator's pool available for bonding.
@@ -109,29 +121,47 @@ contract KeepBonding {
109121 }
110122
111123 /// @notice Withdraws amount from operator's value available for bonding.
112- /// Can be called only by the operator or by the stake owner.
124+ /// Should not be used by grantee of managed grants. For this case,
125+ /// please use `withdrawAsManagedGrantee`.
126+ ///
127+ /// This function can be called only by:
128+ /// - operator,
129+ /// - liquid, staked tokens owner (not a grant),
130+ /// - direct staked tokens grantee (not a managed grant).
131+ ///
113132 /// @param amount Value to withdraw in wei.
114133 /// @param operator Address of the operator.
115134 function withdraw (uint256 amount , address operator ) public {
116135 require (
117136 msg .sender == operator ||
118- msg .sender == tokenStaking.ownerOf (operator),
137+ msg .sender .isTokenOwnerForOperator (operator, tokenStaking) ||
138+ msg .sender .isGranteeForOperator (operator, tokenGrant),
119139 "Only operator or the owner is allowed to withdraw bond "
120140 );
121141
142+ withdrawBond (amount, operator);
143+ }
144+
145+ /// @notice Withdraws amount from operator's value available for bonding.
146+ /// Can be called only by staked tokens managed grantee.
147+ /// @param amount Value to withdraw in wei.
148+ /// @param operator Address of the operator.
149+ /// @param managedGrant Address of the managed grant contract.
150+ function withdrawAsManagedGrantee (
151+ uint256 amount ,
152+ address operator ,
153+ address managedGrant
154+ ) public {
122155 require (
123- unbondedValue[operator] >= amount,
124- "Insufficient unbonded value "
156+ msg .sender .isManagedGranteeForOperator (
157+ operator,
158+ managedGrant,
159+ tokenGrant
160+ ),
161+ "Only grantee is allowed to withdraw bond "
125162 );
126163
127- unbondedValue[operator] = unbondedValue[operator].sub (amount);
128-
129- (bool success , ) = tokenStaking.beneficiaryOf (operator).call.value (
130- amount
131- )("" );
132- require (success, "Transfer failed " );
133-
134- emit UnbondedValueWithdrawn (operator, amount);
164+ withdrawBond (amount, operator);
135165 }
136166
137167 /// @notice Create bond for the given operator, holder, reference and amount.
@@ -329,4 +359,23 @@ contract KeepBonding {
329359 {
330360 return authorizedPools[_operator][_poolAddress];
331361 }
362+
363+ /// @notice Withdraws the provided amount from unbonded value of the
364+ /// provided operator to operator's beneficiary. If there is no enough
365+ /// unbonded value or the transfer failed, function fails.
366+ function withdrawBond (uint256 amount , address operator ) internal {
367+ require (
368+ unbondedValue[operator] >= amount,
369+ "Insufficient unbonded value "
370+ );
371+
372+ unbondedValue[operator] = unbondedValue[operator].sub (amount);
373+
374+ (bool success , ) = tokenStaking.beneficiaryOf (operator).call.value (
375+ amount
376+ )("" );
377+ require (success, "Transfer failed " );
378+
379+ emit UnbondedValueWithdrawn (operator, amount);
380+ }
332381}
0 commit comments