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(*BridgeManager): enhance manager with loose and executor #20

Merged
merged 15 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion script/20231218-maptoken/20231218-maptoken-mainchain.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@ contract Migration__20231215_MapTokenMainchain is BridgeMigration {
uint256 chainId = _config.getCompanionNetwork(_config.getNetworkByChainId(block.chainid)).chainId();

vm.broadcast(sender());
_roninBridgeManager.propose(chainId, expiredTime, targets, values, calldatas, gasAmounts);
_roninBridgeManager.propose(chainId, expiredTime, address(0), false, targets, values, calldatas, gasAmounts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ contract Migration__20231215_MapTokenRoninchain is BridgeMigration {
_verifyRoninProposalGasAmount(targets, values, calldatas, gasAmounts);

vm.broadcast(sender());
_roninBridgeManager.propose(block.chainid, expiredTime, targets, values, calldatas, gasAmounts);
_roninBridgeManager.propose(block.chainid, expiredTime, address(0), false, targets, values, calldatas, gasAmounts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ contract Migration__MapTokenMainchain is BridgeMigration {
_roninBridgeManager.propose(
chainId,
expiredTime,
address(0),
false,
targets,
values,
calldatas,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ contract Migration__MapTokenRoninchain is BridgeMigration {
_roninBridgeManager.propose(
block.chainid,
expiredTime,
address(0),
false,
targets,
values,
calldatas,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ contract Migration__20240131_MapTokenPixelMainchain is BridgeMigration, Migratio
_roninBridgeManager.propose(
chainId,
expiredTime,
address(0),
false,
targets,
values,
calldatas,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ contract Migration__20240131_MapTokenPixelRoninchain is BridgeMigration, Migrati
_roninBridgeManager.propose(
block.chainid,
expiredTime,
address(0),
false,
targets,
values,
calldatas,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ contract Migration__20240206_MapTokenBananaMainchain is

console2.log("Nonce:", vm.getNonce(_governor));
vm.broadcast(_governor);
_roninBridgeManager.propose(chainId, expiredTime, targets, values, calldatas, gasAmounts);
_roninBridgeManager.propose(chainId, expiredTime, address(0), false, targets, values, calldatas, gasAmounts);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ contract Migration__20240206_MapTokenBananaRoninChain is

roninTokensToSetMinThreshold[1] = pixelRoninToken;
minThresholds[1] = pixelMinThreshold;

roninTokensToSetMinThreshold[2] = pixelMainchainToken;
minThresholds[2] = 0;

Expand Down Expand Up @@ -152,7 +152,7 @@ contract Migration__20240206_MapTokenBananaRoninChain is

console2.log("Nonce:", vm.getNonce(_governor));
vm.broadcast(_governor);
_roninBridgeManager.propose(block.chainid, expiredTime, targets, values, calldatas, gasAmounts);
_roninBridgeManager.propose(block.chainid, expiredTime, address(0), false, targets, values, calldatas, gasAmounts);

// ============= LOCAL SIMULATION ==================
_cheatWeightOperator(_governor);
Expand Down
6 changes: 3 additions & 3 deletions src/extensions/bridge-operator-governance/BridgeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ abstract contract BridgeManager is IBridgeManager, Initializable, HasContracts,
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,bytes32 salt)"),
keccak256("BridgeAdmin"), // name hash
keccak256("2"), // version hash
keccak256(abi.encode("BRIDGE_ADMIN", roninChainId)) // salt
keccak256("BridgeManager"), // name hash
keccak256("3"), // version hash
keccak256(abi.encode("BRIDGE_MANAGER", roninChainId)) // salt
)
);

Expand Down
25 changes: 23 additions & 2 deletions src/extensions/sequential-governance/CoreGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ abstract contract CoreGovernance is Initializable, SignatureConsumer, VoteStatus
function _proposeProposal(
uint256 chainId,
uint256 expiryTimestamp,
address executor,
bool loose,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
Expand All @@ -118,7 +120,7 @@ abstract contract CoreGovernance is Initializable, SignatureConsumer, VoteStatus
if (chainId == 0) revert ErrInvalidChainId(msg.sig, 0, block.chainid);
uint256 round_ = _createVotingRound(chainId);

proposal = Proposal.ProposalDetail(round_, chainId, expiryTimestamp, targets, values, calldatas, gasAmounts);
proposal = Proposal.ProposalDetail(round_, chainId, expiryTimestamp, executor, loose, targets, values, calldatas, gasAmounts);
proposal.validate(_proposalExpiryDuration);

bytes32 proposalHash = proposal.hash();
Expand Down Expand Up @@ -204,14 +206,33 @@ abstract contract CoreGovernance is Initializable, SignatureConsumer, VoteStatus
done = true;
_vote.status = VoteStatus.Approved;
emit ProposalApproved(_vote.hash);
_tryExecute(_vote, proposal);
if (proposal.isAutoExecute()) {
_tryExecute(_vote, proposal);
}
} else if (_againstVoteWeight >= minimumAgainstVoteWeight) {
done = true;
_vote.status = VoteStatus.Rejected;
emit ProposalRejected(_vote.hash);
}
}

/**
* @dev The specified executor executes the proposal on an approved proposal.
*/
function _executeWithCaller(Proposal.ProposalDetail memory proposal, address caller) internal {
bytes32 proposalHash = proposal.hash();
ProposalVote storage _vote = vote[proposal.chainId][proposal.nonce];

if (_vote.hash != proposalHash) {
revert ErrInvalidProposal(proposalHash, _vote.hash);
}

if (_vote.status != VoteStatus.Approved) revert ErrProposalNotApproved();
if (caller != proposal.executor) revert ErrInvalidExecutor();

_tryExecute(_vote, proposal);
}

/**
* @dev When the contract is on Ronin chain, checks whether the proposal is expired and delete it if is expired.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ abstract contract GlobalCoreGovernance is CoreGovernance {
function _proposeGlobal(
uint256 expiryTimestamp,
GlobalProposal.TargetOption[] calldata targetOptions,
address executor,
bool loose,
uint256[] memory values,
bytes[] memory calldatas,
uint256[] memory gasAmounts,
address creator
) internal virtual {
uint256 round_ = _createVotingRound(0);
GlobalProposal.GlobalProposalDetail memory globalProposal =
GlobalProposal.GlobalProposalDetail(round_, expiryTimestamp, targetOptions, values, calldatas, gasAmounts);
GlobalProposal.GlobalProposalDetail(round_, expiryTimestamp, executor, loose, targetOptions, values, calldatas, gasAmounts);
Proposal.ProposalDetail memory proposal = globalProposal.intoProposalDetail(_resolveTargets({ targetOptions: targetOptions, strict: true }));
proposal.validate(_proposalExpiryDuration);

Expand Down Expand Up @@ -82,6 +84,11 @@ abstract contract GlobalCoreGovernance is CoreGovernance {
emit GlobalProposalCreated(round_, proposalHash, proposal, globalProposal.hash(), globalProposal, creator);
}

function _executeGlobalWithCaller(GlobalProposal.GlobalProposalDetail memory globalProposal, address caller) internal {
Proposal.ProposalDetail memory proposal = globalProposal.intoProposalDetail(_resolveTargets({ targetOptions: globalProposal.targetOptions, strict: true }));
_executeWithCaller(proposal, caller);
}

/**
* @dev Returns corresponding address of target options. Return address(0) on non-existent target.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ import "../CoreGovernance.sol";
abstract contract CommonGovernanceProposal is CoreGovernance {
using Proposal for Proposal.ProposalDetail;

/**
* @dev Error thrown when an invalid proposal is encountered.
* @param actual The actual value of the proposal.
* @param expected The expected value of the proposal.
*/
error ErrInvalidProposal(bytes32 actual, bytes32 expected);

/**
* @dev Casts votes by signatures.
*
Expand Down
55 changes: 29 additions & 26 deletions src/libraries/GlobalProposal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ library GlobalProposal {
// Nonce to make sure proposals are executed in order
uint256 nonce;
uint256 expiryTimestamp;
address executor;
bool loose;
TargetOption[] targetOptions;
uint256[] values;
bytes[] calldatas;
uint256[] gasAmounts;
}

// keccak256("GlobalProposalDetail(uint256 nonce,uint256 expiryTimestamp,uint8[] targetOptions,uint256[] values,bytes[] calldatas,uint256[] gasAmounts)");
bytes32 public constant TYPE_HASH = 0x1463f426c05aff2c1a7a0957a71c9898bc8b47142540538e79ee25ee91141350;
// keccak256("GlobalProposalDetail(uint256 nonce,uint256 expiryTimestamp,address executor,bool loose,uint8[] targetOptions,uint256[] values,bytes[] calldatas,uint256[] gasAmounts)");
bytes32 internal constant TYPE_HASH = 0x8fdb3bc7211cb44f39a2cae84127672c4570a00720dfbf2bb58285070faa28da;

/**
* @dev Returns struct hash of the proposal.
Expand All @@ -39,7 +41,7 @@ library GlobalProposal {
bytes32[] memory calldataHashList = new bytes32[](self.calldatas.length);
uint256[] memory gasAmounts = self.gasAmounts;

for (uint256 i; i < calldataHashList.length; ) {
for (uint256 i; i < calldataHashList.length;) {
calldataHashList[i] = keccak256(self.calldatas[i]);

unchecked {
Expand All @@ -52,54 +54,55 @@ library GlobalProposal {
* keccak256(
* abi.encode(
* TYPE_HASH,
* _proposal.nonce,
* _proposal.expiryTimestamp,
* _targetsHash,
* _valuesHash,
* _calldatasHash,
* _gasAmountsHash
* proposal.nonce,
* proposal.expiryTimestamp,
* proposal.executor,
* proposal.loose,
* targetsHash,
* valuesHash,
* calldatasHash,
* gasAmountsHash
* )
* );
*/
assembly {
let ptr := mload(0x40)
mstore(ptr, TYPE_HASH)
mstore(add(ptr, 0x20), mload(self)) // _proposal.nonce
mstore(add(ptr, 0x40), mload(add(self, 0x20))) // _proposal.expiryTimestamp
mstore(add(ptr, 0x20), mload(self)) // proposal.nonce
mstore(add(ptr, 0x40), mload(add(self, 0x20))) // proposal.expiryTimestamp
mstore(add(ptr, 0x60), mload(add(self, 0x40))) // proposal.executor
mstore(add(ptr, 0x80), mload(add(self, 0x60))) // proposal.loose

let arrayHashed
arrayHashed := keccak256(add(targets, 32), mul(mload(targets), 32)) // targetsHash
mstore(add(ptr, 0x60), arrayHashed)
arrayHashed := keccak256(add(values, 32), mul(mload(values), 32)) // _valuesHash
mstore(add(ptr, 0x80), arrayHashed)
arrayHashed := keccak256(add(calldataHashList, 32), mul(mload(calldataHashList), 32)) // _calldatasHash
mstore(add(ptr, 0xa0), arrayHashed)
arrayHashed := keccak256(add(gasAmounts, 32), mul(mload(gasAmounts), 32)) // _gasAmountsHash
arrayHashed := keccak256(add(values, 32), mul(mload(values), 32)) // valuesHash
mstore(add(ptr, 0xc0), arrayHashed)
digest_ := keccak256(ptr, 0xe0)
arrayHashed := keccak256(add(calldataHashList, 32), mul(mload(calldataHashList), 32)) // calldatasHash
mstore(add(ptr, 0xe0), arrayHashed)
arrayHashed := keccak256(add(gasAmounts, 32), mul(mload(gasAmounts), 32)) // gasAmountsHash
mstore(add(ptr, 0x100), arrayHashed)
digest_ := keccak256(ptr, 0x120)
}
}

/**
* @dev Converts into the normal proposal.
*/
function intoProposalDetail(
GlobalProposalDetail memory self,
address[] memory targets
) internal pure returns (Proposal.ProposalDetail memory detail_) {
function intoProposalDetail(GlobalProposalDetail memory self, address[] memory targets) internal pure returns (Proposal.ProposalDetail memory detail_) {
detail_.nonce = self.nonce;
detail_.expiryTimestamp = self.expiryTimestamp;
detail_.chainId = 0;
detail_.expiryTimestamp = self.expiryTimestamp;
detail_.executor = self.executor;
detail_.loose = self.loose;

detail_.targets = new address[](self.targetOptions.length);
detail_.values = self.values;
detail_.calldatas = self.calldatas;
detail_.gasAmounts = self.gasAmounts;

for (uint256 i; i < self.targetOptions.length; ) {
for (uint256 i; i < self.targetOptions.length; ++i) {
detail_.targets[i] = targets[i];
unchecked {
++i;
}
}
}
}
Loading