Skip to content

Commit

Permalink
feat(contracts/core): support user stake delegation (#2681)
Browse files Browse the repository at this point in the history
Added _initial_ support for user stake delegation to the `Staking`
contract, and updated related Go. I also added support for delegating on
behalf of other users. The omni CLI delegate command was only updated
for the new delegate function interface, so CLI still only supports
self-delegation, for now.

It has yet to be determined what contract changes, if any, are necessary
for unstaking. This contract should not be upgraded yet until the entire
scope is known.

issue: #567
  • Loading branch information
Zodomo authored Dec 20, 2024
1 parent 1d467a4 commit eb04c6d
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 33 deletions.
2 changes: 1 addition & 1 deletion contracts/allocs/devnet.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/allocs/staging.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/bindings/admin.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/bindings/allocpredeploys.go

Large diffs are not rendered by default.

25 changes: 23 additions & 2 deletions contracts/bindings/staking.go

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions contracts/core/.gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Admin_Test:test_pause_unpause() (gas: 33933914)
Admin_Test:test_pause_unpause_bridge() (gas: 28963667)
Admin_Test:test_pause_unpause_xcall() (gas: 33887888)
Admin_Test:test_pause_unpause_xsubmit() (gas: 33887595)
Admin_Test:test_upgrade() (gas: 37969089)
AllocPredeploys_Test:test_num_allocs() (gas: 1181319043)
AllocPredeploys_Test:test_predeploys() (gas: 1181300853)
AllocPredeploys_Test:test_preinstalls() (gas: 1182017269)
AllocPredeploys_Test:test_proxies() (gas: 1408944070)
Admin_Test:test_pause_unpause() (gas: 34028415)
Admin_Test:test_pause_unpause_bridge() (gas: 29058168)
Admin_Test:test_pause_unpause_xcall() (gas: 33982389)
Admin_Test:test_pause_unpause_xsubmit() (gas: 33982096)
Admin_Test:test_upgrade() (gas: 38063590)
AllocPredeploys_Test:test_num_allocs() (gas: 1181319931)
AllocPredeploys_Test:test_predeploys() (gas: 1181301741)
AllocPredeploys_Test:test_preinstalls() (gas: 1182018157)
AllocPredeploys_Test:test_proxies() (gas: 1408944958)
FeeOracleV1_Test:test_bulkSetFeeParams() (gas: 173154)
FeeOracleV1_Test:test_feeFor() (gas: 122830)
FeeOracleV1_Test:test_setBaseGasLimit() (gas: 32375)
Expand Down Expand Up @@ -150,7 +150,7 @@ Quorum_Test:test_verify_succeeds() (gas: 294059)
Slashing_Test:test_stub() (gas: 143)
Slashing_Test:test_unjail() (gas: 54734)
Staking_Test:test_createValidator() (gas: 145288)
Staking_Test:test_delegate() (gas: 110001)
Staking_Test:test_delegate() (gas: 98848)
Staking_Test:test_stub() (gas: 143)
Upgrade_Test:test_stub() (gas: 143)
XAppUpgradeable_Test:test_isXCall() (gas: 148924)
Expand Down
7 changes: 6 additions & 1 deletion contracts/core/script/admin/StakingPostUpgradeTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,16 @@ contract StakingPostUpgradeTest is Test {

function _testDelegate() internal {
uint256 deposit = staking.MinDelegation();
vm.deal(validator, deposit);
vm.deal(validator, deposit * 2);

vm.expectEmit();
emit Staking.Delegate(validator, validator, deposit);
vm.prank(validator);
staking.delegate{ value: deposit }(validator);

vm.expectEmit();
emit Staking.Delegate(validator, validator, deposit);
vm.prank(validator);
staking.delegateFor{ value: deposit }(validator, validator);
}
}
32 changes: 23 additions & 9 deletions contracts/core/src/octane/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,21 @@ contract Staking is OwnableUpgradeable, EIP712Upgradeable {
}

/**
* @notice Increase your validators self delegation.
* NOTE: Only self delegations to existing validators are currently supported.
* If msg.sender is not a validator, the delegation will be lost.
* @notice Delegate tokens to a validator
* @dev Proxies x/staking.MsgDelegate
* @param validator The address of the validator to delegate to
*/
function delegate(address validator) external payable {
require(!isAllowlistEnabled || isAllowedValidator[validator], "Staking: not allowed val");
require(msg.value >= MinDelegation, "Staking: insufficient deposit");

// only support self delegation for now
require(msg.sender == validator, "Staking: only self delegation");
_delegate(msg.sender, validator);
}

emit Delegate(msg.sender, validator, msg.value);
/**
* @notice Delegate tokens to a validator for another address
* @param delegator The address of the delegator
* @param validator The address of the validator to delegate to
*/
function delegateFor(address delegator, address validator) external payable {
_delegate(delegator, validator);
}

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -220,4 +222,16 @@ contract Staking is OwnableUpgradeable, EIP712Upgradeable {
address pubKeyAddress = Secp256k1.pubkeyToAddress(x, y);
return recovered == pubKeyAddress;
}

/**
* @notice Delegate tokens to a validator
* @param delegator The address of the delegator
* @param validator The address of the validator to delegate to
*/
function _delegate(address delegator, address validator) internal {
require(!isAllowlistEnabled || isAllowedValidator[validator], "Staking: not allowed val");
require(msg.value >= MinDelegation, "Staking: insufficient deposit");

emit Delegate(delegator, validator, msg.value);
}
}
6 changes: 0 additions & 6 deletions contracts/core/test/octane/Staking.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,13 @@ contract Staking_Test is Test {

function test_delegate() public {
// requires min delegation
address validator = makeAddr("validator");
uint256 minDelegation = staking.MinDelegation();

vm.deal(validator, minDelegation);

vm.expectRevert("Staking: insufficient deposit");
staking.delegate{ value: minDelegation - 1 }(validator);

// requires self-delegation
vm.expectRevert("Staking: only self delegation");
vm.prank(validator);
staking.delegate{ value: minDelegation }(makeAddr("someone else"));

// if allowlist enabled, must be in allowlist
vm.prank(owner);
staking.enableAllowlist();
Expand Down
Loading

0 comments on commit eb04c6d

Please sign in to comment.