Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement bep-341 and bep-410 #574

Merged
merged 9 commits into from
Jul 22, 2024
11 changes: 8 additions & 3 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@ jobs:
run: |
forge build

- name: Set RPC Env
run: echo "RPC_BSC=https://bsc-dataseed.bnbchain.org" >> $GITHUB_ENV
- name: Start Local Chain
run: |
npm install pm2 -g
pm2 start --name local-chain "anvil -f https://bsc-dataseed.bnbchain.org"
sleep 5
env:
PORT: 8545

- name: Unit Test
run: |
forge test
forge test --rpc-url http://127.0.0.1:8545
43 changes: 41 additions & 2 deletions abi/bscvalidatorset.abi
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getTurnLength",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getValidators",
Expand Down Expand Up @@ -1239,7 +1252,20 @@
},
{
"type": "function",
"name": "systemRewardRatio",
"name": "systemRewardAntiMEVRatio",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "systemRewardBaseRatio",
"inputs": [],
"outputs": [
{
Expand All @@ -1263,6 +1289,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "turnLength",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "updateParam",
Expand Down Expand Up @@ -1684,4 +1723,4 @@
"inputs": [],
"anonymous": false
}
]
]
86 changes: 86 additions & 0 deletions abi/stakehub.abi
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "agentToOperator",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "blackList",
Expand Down Expand Up @@ -447,6 +466,25 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getValidatorAgent",
"inputs": [
{
"name": "operatorAddress",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getValidatorBasicInfo",
Expand Down Expand Up @@ -1032,6 +1070,19 @@
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "updateAgent",
"inputs": [
{
"name": "newAgent",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "updateParam",
Expand Down Expand Up @@ -1088,6 +1139,31 @@
],
"stateMutability": "view"
},
{
"type": "event",
"name": "AgentChanged",
"inputs": [
{
"name": "operatorAddress",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "oldAgent",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newAgent",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "BlackListed",
Expand Down Expand Up @@ -1656,6 +1732,11 @@
"name": "InBlackList",
"inputs": []
},
{
"type": "error",
"name": "InvalidAgent",
"inputs": []
},
{
"type": "error",
"name": "InvalidCommission",
Expand All @@ -1681,6 +1762,11 @@
"name": "InvalidSynPackage",
"inputs": []
},
{
"type": "error",
"name": "InvalidValidator",
"inputs": []
},
{
"type": "error",
"name": "InvalidValue",
Expand Down
73 changes: 64 additions & 9 deletions contracts/BC_fusion/StakeHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ contract StakeHub is System, Initializable, Protectable {
error ConsensusAddressExpired();
// @notice signature: 0x0d7b78d4
error InvalidSynPackage();
// @notice signature: 0xbebdc757
error InvalidAgent();
// @notice signature: 0x682a6e7c
error InvalidValidator();

/*----------------- storage -----------------*/
uint8 private _receiveFundStatus;
Expand Down Expand Up @@ -135,6 +139,9 @@ contract StakeHub is System, Initializable, Protectable {
// slash key => slash jail time
mapping(bytes32 => uint256) private _felonyRecords;

// agent => validator operator address
mapping(address => address) public agentToOperator;

/*----------------- structs and events -----------------*/
struct StakeMigrationPackage {
address operatorAddress; // the operator address of the target validator to delegate to
Expand Down Expand Up @@ -162,7 +169,9 @@ contract StakeHub is System, Initializable, Protectable {
bool jailed;
uint256 jailUntil;
uint256 updateTime;
uint256[20] __reservedSlots;
// The agent can perform transactions on behalf of the operatorAddress in certain scenarios.
address agent;
uint256[19] __reservedSlots;
}

struct Description {
Expand Down Expand Up @@ -219,6 +228,7 @@ contract StakeHub is System, Initializable, Protectable {
address indexed operatorAddress, address indexed delegator, uint256 bnbAmount, StakeMigrationRespCode respCode
);
event UnexpectedPackage(uint8 channelId, bytes msgBytes);
event AgentChanged(address indexed operatorAddress, address indexed oldAgent, address indexed newAgent);

/*----------------- modifiers -----------------*/
modifier validatorExist(address operatorAddress) {
Expand Down Expand Up @@ -315,6 +325,27 @@ contract StakeHub is System, Initializable, Protectable {
}

/*----------------- external functions -----------------*/
/**
* @param newAgent the new agent address of the validator, updating to address(0) means remove the old agent.
*/
function updateAgent(address newAgent) external validatorExist(msg.sender) whenNotPaused notInBlackList {
if (agentToOperator[newAgent] != address(0)) revert InvalidAgent();
if (_validatorSet.contains(newAgent)) revert InvalidAgent();

address operatorAddress = msg.sender;
address oldAgent = _validators[operatorAddress].agent;
if (oldAgent == newAgent) revert InvalidAgent();

if (oldAgent != address(0)) {
delete agentToOperator[oldAgent];
}

_validators[operatorAddress].agent = newAgent;
agentToOperator[newAgent] = operatorAddress;

emit AgentChanged(operatorAddress, oldAgent, newAgent);
}

/**
* @param consensusAddress the consensus address of the validator
* @param voteAddress the vote address of the validator
Expand All @@ -332,6 +363,8 @@ contract StakeHub is System, Initializable, Protectable {
// basic check
address operatorAddress = msg.sender;
if (_validatorSet.contains(operatorAddress)) revert ValidatorExisted();
if (agentToOperator[operatorAddress] != address(0)) revert InvalidValidator();

if (consensusToOperator[consensusAddress] != address(0) || _legacyConsensusAddress[consensusAddress]) {
revert DuplicateConsensusAddress();
}
Expand Down Expand Up @@ -384,14 +417,14 @@ contract StakeHub is System, Initializable, Protectable {
external
whenNotPaused
notInBlackList
validatorExist(msg.sender)
validatorExist(_bep410MsgSender())
{
if (newConsensusAddress == address(0)) revert InvalidConsensusAddress();
if (consensusToOperator[newConsensusAddress] != address(0) || _legacyConsensusAddress[newConsensusAddress]) {
revert DuplicateConsensusAddress();
}

address operatorAddress = msg.sender;
address operatorAddress = _bep410MsgSender();
Validator storage valInfo = _validators[operatorAddress];
if (valInfo.updateTime + BREATHE_BLOCK_INTERVAL > block.timestamp) revert UpdateTooFrequently();

Expand All @@ -410,9 +443,9 @@ contract StakeHub is System, Initializable, Protectable {
external
whenNotPaused
notInBlackList
validatorExist(msg.sender)
validatorExist(_bep410MsgSender())
{
address operatorAddress = msg.sender;
address operatorAddress = _bep410MsgSender();
Validator storage valInfo = _validators[operatorAddress];
if (valInfo.updateTime + BREATHE_BLOCK_INTERVAL > block.timestamp) revert UpdateTooFrequently();

Expand All @@ -436,9 +469,9 @@ contract StakeHub is System, Initializable, Protectable {
external
whenNotPaused
notInBlackList
validatorExist(msg.sender)
validatorExist(_bep410MsgSender())
{
address operatorAddress = msg.sender;
address operatorAddress = _bep410MsgSender();
Validator storage valInfo = _validators[operatorAddress];
if (valInfo.updateTime + BREATHE_BLOCK_INTERVAL > block.timestamp) revert UpdateTooFrequently();

Expand All @@ -456,9 +489,9 @@ contract StakeHub is System, Initializable, Protectable {
function editVoteAddress(
bytes calldata newVoteAddress,
bytes calldata blsProof
) external whenNotPaused notInBlackList validatorExist(msg.sender) {
) external whenNotPaused notInBlackList validatorExist(_bep410MsgSender()) {
// proof-of-possession verify
address operatorAddress = msg.sender;
address operatorAddress = _bep410MsgSender();
if (!_checkVoteAddress(operatorAddress, newVoteAddress, blsProof)) revert InvalidVoteAddress();
if (voteToOperator[newVoteAddress] != address(0) || _legacyVoteAddress[newVoteAddress]) {
revert DuplicateVoteAddress();
Expand Down Expand Up @@ -955,6 +988,20 @@ contract StakeHub is System, Initializable, Protectable {
return _validators[operatorAddress].commission;
}

/**
* @param operatorAddress the operator address of the validator
*
* @return the agent of a validator
*/
function getValidatorAgent(address operatorAddress)
external
view
validatorExist(operatorAddress)
returns (address)
{
return _validators[operatorAddress].agent;
}

/**
* @dev this function will be used by Parlia consensus engine.
*
Expand Down Expand Up @@ -1179,4 +1226,12 @@ contract StakeHub is System, Initializable, Protectable {
uint256 bnbAmount = IStakeCredit(_validators[operatorAddress].creditContract).claim(msg.sender, requestNumber);
emit Claimed(operatorAddress, msg.sender, bnbAmount);
}

function _bep410MsgSender() internal view returns (address) {
if (agentToOperator[msg.sender] != address(0)) {
return agentToOperator[msg.sender];
}

return msg.sender;
}
}
2 changes: 1 addition & 1 deletion contracts/BC_fusion/lib/RLPDecode.sol
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ library RLPDecode {
assembly {
result := mload(memPtr)

// shfit to the correct location if neccesary
// shift to the correct location if necessary
if lt(len, 32) { result := div(result, exp(256, sub(32, len))) }
}

Expand Down
Loading
Loading