Skip to content

Commit

Permalink
chore: an extra getter + easier override
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed Dec 3, 2024
1 parent 01cf9fe commit 93491d1
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 75 deletions.
8 changes: 8 additions & 0 deletions l1-contracts/src/core/interfaces/IStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ struct Exit {
}

interface IStaking {
event Deposit(
address indexed attester, address indexed proposer, address indexed withdrawer, uint256 amount
);
event WithdrawInitiated(address indexed attester, address indexed recipient, uint256 amount);
event WithdrawFinalised(address indexed attester, address indexed recipient, uint256 amount);
event Slashed(address indexed attester, uint256 amount);

function deposit(address _attester, address _proposer, address _withdrawer, uint256 _amount)
external;
function initiateWithdraw(address _attester, address _recipient) external returns (bool);
Expand All @@ -45,5 +52,6 @@ interface IStaking {
function getActiveAttesterCount() external view returns (uint256);
function getAttesterAtIndex(uint256 _index) external view returns (address);
function getProposerAtIndex(uint256 _index) external view returns (address);
function getProposerForAttester(address _attester) external view returns (address);
function getOperatorAtIndex(uint256 _index) external view returns (OperatorInfo memory);
}
130 changes: 67 additions & 63 deletions l1-contracts/src/core/staking/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,70 +28,12 @@ contract Staking is IStaking {
mapping(address attester => ValidatorInfo) internal info;
mapping(address attester => Exit) internal exits;

event Deposit(
address indexed attester, address indexed proposer, address indexed withdrawer, uint256 amount
);
event WithdrawInitiated(address indexed attester, address indexed recipient, uint256 amount);
event WithdrawFinalised(address indexed attester, address indexed recipient, uint256 amount);
event Slashed(address indexed attester, uint256 amount);

constructor(address _slasher, IERC20 _stakingAsset, uint256 _minimumStake) {
SLASHER = _slasher;
STAKING_ASSET = _stakingAsset;
MINIMUM_STAKE = _minimumStake;
}

function deposit(address _attester, address _proposer, address _withdrawer, uint256 _amount)
external
override(IStaking)
{
require(_amount >= MINIMUM_STAKE, Errors.Staking__InsufficientStake(_amount, MINIMUM_STAKE));
STAKING_ASSET.transferFrom(msg.sender, address(this), _amount);
require(info[_attester].status == Status.NONE, Errors.Staking__AlreadyRegistered(_attester));
require(attesters.add(_attester), Errors.Staking__AlreadyActive(_attester));

// If BLS, need to check possession of private key to avoid attacks.

info[_attester] = ValidatorInfo({
stake: _amount,
withdrawer: _withdrawer,
proposer: _proposer,
status: Status.VALIDATING
});

emit Deposit(_attester, _proposer, _withdrawer, _amount);
}

function initiateWithdraw(address _attester, address _recipient)
external
override(IStaking)
returns (bool)
{
ValidatorInfo storage validator = info[_attester];

require(
msg.sender == validator.withdrawer,
Errors.Staking__NotWithdrawer(validator.withdrawer, msg.sender)
);
require(
validator.status == Status.VALIDATING || validator.status == Status.LIVING,
Errors.Staking__NothingToExit(_attester)
);
if (validator.status == Status.VALIDATING) {
require(attesters.remove(_attester), Errors.Staking__FailedToRemove(_attester));
}

// Note that the "amount" is not stored here, but reusing the `validators`
// We always exit fully.
exits[_attester] =
Exit({exitableAt: Timestamp.wrap(block.timestamp) + EXIT_DELAY, recipient: _recipient});
validator.status = Status.EXITING;

emit WithdrawInitiated(_attester, _recipient, validator.stake);

return true;
}

function finaliseWithdraw(address _attester) external override(IStaking) {
ValidatorInfo storage validator = info[_attester];
require(validator.status == Status.EXITING, Errors.Staking__NotExiting(_attester));
Expand All @@ -110,7 +52,7 @@ contract Staking is IStaking {

STAKING_ASSET.transfer(recipient, amount);

emit WithdrawFinalised(_attester, recipient, amount);
emit IStaking.WithdrawFinalised(_attester, recipient, amount);
}

function slash(address _attester, uint256 _amount) external override(IStaking) {
Expand Down Expand Up @@ -149,12 +91,17 @@ contract Staking is IStaking {
return info[_attester];
}

function getExit(address _attester) external view override(IStaking) returns (Exit memory) {
return exits[_attester];
function getProposerForAttester(address _attester)
external
view
override(IStaking)
returns (address)
{
return info[_attester].proposer;
}

function getActiveAttesterCount() external view override(IStaking) returns (uint256) {
return attesters.length();
function getExit(address _attester) external view override(IStaking) returns (Exit memory) {
return exits[_attester];
}

function getAttesterAtIndex(uint256 _index) external view override(IStaking) returns (address) {
Expand All @@ -174,4 +121,61 @@ contract Staking is IStaking {
address attester = attesters.at(_index);
return OperatorInfo({proposer: info[attester].proposer, attester: attester});
}

function deposit(address _attester, address _proposer, address _withdrawer, uint256 _amount)
public
virtual
override(IStaking)
{
require(_amount >= MINIMUM_STAKE, Errors.Staking__InsufficientStake(_amount, MINIMUM_STAKE));
STAKING_ASSET.transferFrom(msg.sender, address(this), _amount);
require(info[_attester].status == Status.NONE, Errors.Staking__AlreadyRegistered(_attester));
require(attesters.add(_attester), Errors.Staking__AlreadyActive(_attester));

// If BLS, need to check possession of private key to avoid attacks.

info[_attester] = ValidatorInfo({
stake: _amount,
withdrawer: _withdrawer,
proposer: _proposer,
status: Status.VALIDATING
});

emit IStaking.Deposit(_attester, _proposer, _withdrawer, _amount);
}

function initiateWithdraw(address _attester, address _recipient)
public
virtual
override(IStaking)
returns (bool)
{
ValidatorInfo storage validator = info[_attester];

require(
msg.sender == validator.withdrawer,
Errors.Staking__NotWithdrawer(validator.withdrawer, msg.sender)
);
require(
validator.status == Status.VALIDATING || validator.status == Status.LIVING,
Errors.Staking__NothingToExit(_attester)
);
if (validator.status == Status.VALIDATING) {
require(attesters.remove(_attester), Errors.Staking__FailedToRemove(_attester));
}

// Note that the "amount" is not stored here, but reusing the `validators`
// We always exit fully.
exits[_attester] =
Exit({exitableAt: Timestamp.wrap(block.timestamp) + EXIT_DELAY, recipient: _recipient});
validator.status = Status.EXITING;

emit IStaking.WithdrawInitiated(_attester, _recipient, validator.stake);

return true;
}

function getActiveAttesterCount() public view override(IStaking) returns (uint256) {
return attesters.length();
}
}
4 changes: 2 additions & 2 deletions l1-contracts/test/staking/deposit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity >=0.8.27;
import {StakingBase} from "./base.t.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {IERC20Errors} from "@oz/interfaces/draft-IERC6093.sol";
import {Staking, Status, ValidatorInfo} from "@aztec/core/staking/Staking.sol";
import {Staking, IStaking, Status, ValidatorInfo} from "@aztec/core/staking/Staking.sol";

contract DepositTest is StakingBase {
uint256 internal depositAmount;
Expand Down Expand Up @@ -147,7 +147,7 @@ contract DepositTest is StakingBase {
assertEq(stakingAsset.balanceOf(address(staking)), 0);

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.Deposit(ATTESTER, PROPOSER, WITHDRAWER, depositAmount);
emit IStaking.Deposit(ATTESTER, PROPOSER, WITHDRAWER, depositAmount);

staking.deposit({
_attester: ATTESTER,
Expand Down
5 changes: 2 additions & 3 deletions l1-contracts/test/staking/finaliseWithdraw.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ pragma solidity >=0.8.27;

import {StakingBase} from "./base.t.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {IERC20Errors} from "@oz/interfaces/draft-IERC6093.sol";
import {Staking, Status, ValidatorInfo, Exit} from "@aztec/core/staking/Staking.sol";
import {IStaking, Status, ValidatorInfo, Exit} from "@aztec/core/staking/Staking.sol";
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";

contract FinaliseWithdrawTest is StakingBase {
Expand Down Expand Up @@ -69,7 +68,7 @@ contract FinaliseWithdrawTest is StakingBase {
vm.warp(Timestamp.unwrap(exit.exitableAt));

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.WithdrawFinalised(ATTESTER, RECIPIENT, MINIMUM_STAKE);
emit IStaking.WithdrawFinalised(ATTESTER, RECIPIENT, MINIMUM_STAKE);
staking.finaliseWithdraw(ATTESTER);

exit = staking.getExit(ATTESTER);
Expand Down
5 changes: 5 additions & 0 deletions l1-contracts/test/staking/getters.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ contract GettersTest is StakingBase {
vm.expectRevert();
staking.getOperatorAtIndex(1);
}

function test_getProposerForAttester() external view {
assertEq(staking.getProposerForAttester(ATTESTER), PROPOSER);
assertEq(staking.getProposerForAttester(address(1)), address(0));
}
}
6 changes: 3 additions & 3 deletions l1-contracts/test/staking/initiateWithdraw.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity >=0.8.27;

import {StakingBase} from "./base.t.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {Staking, Status, ValidatorInfo, Exit} from "@aztec/core/staking/Staking.sol";
import {IStaking, Status, ValidatorInfo, Exit} from "@aztec/core/staking/Staking.sol";
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";

contract InitiateWithdrawTest is StakingBase {
Expand Down Expand Up @@ -104,7 +104,7 @@ contract InitiateWithdrawTest is StakingBase {
assertEq(staking.getActiveAttesterCount(), 1);

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.WithdrawInitiated(ATTESTER, RECIPIENT, MINIMUM_STAKE);
emit IStaking.WithdrawInitiated(ATTESTER, RECIPIENT, MINIMUM_STAKE);

vm.prank(WITHDRAWER);
staking.initiateWithdraw(ATTESTER, RECIPIENT);
Expand Down Expand Up @@ -137,7 +137,7 @@ contract InitiateWithdrawTest is StakingBase {
assertEq(staking.getActiveAttesterCount(), 0);

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.WithdrawInitiated(ATTESTER, RECIPIENT, MINIMUM_STAKE);
emit IStaking.WithdrawInitiated(ATTESTER, RECIPIENT, MINIMUM_STAKE);

vm.prank(WITHDRAWER);
staking.initiateWithdraw(ATTESTER, RECIPIENT);
Expand Down
8 changes: 4 additions & 4 deletions l1-contracts/test/staking/slash.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity >=0.8.27;

import {StakingBase} from "./base.t.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {Staking, Status, ValidatorInfo, Exit} from "@aztec/core/staking/Staking.sol";
import {Staking, IStaking, Status, ValidatorInfo, Exit} from "@aztec/core/staking/Staking.sol";
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";

contract SlashTest is StakingBase {
Expand Down Expand Up @@ -82,7 +82,7 @@ contract SlashTest is StakingBase {
assertTrue(info.status == Status.EXITING);

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.Slashed(ATTESTER, 1);
emit IStaking.Slashed(ATTESTER, 1);
vm.prank(SLASHER);
staking.slash(ATTESTER, 1);

Expand Down Expand Up @@ -112,7 +112,7 @@ contract SlashTest is StakingBase {
uint256 balance = info.stake;

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.Slashed(ATTESTER, 1);
emit IStaking.Slashed(ATTESTER, 1);
vm.prank(SLASHER);
staking.slash(ATTESTER, 1);

Expand Down Expand Up @@ -162,7 +162,7 @@ contract SlashTest is StakingBase {
uint256 balance = info.stake;

vm.expectEmit(true, true, true, true, address(staking));
emit Staking.Slashed(ATTESTER, slashingAmount);
emit IStaking.Slashed(ATTESTER, slashingAmount);
vm.prank(SLASHER);
staking.slash(ATTESTER, slashingAmount);

Expand Down

0 comments on commit 93491d1

Please sign in to comment.