Skip to content

Commit

Permalink
Proxy batch delegation (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
giuseppecrj authored Jun 3, 2024
1 parent 9820892 commit ed8f157
Show file tree
Hide file tree
Showing 23 changed files with 414 additions and 487 deletions.
4 changes: 2 additions & 2 deletions contracts/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ verify-blockscout-base-sepolia :;

deploy-sepolia :;
@echo "Deploying $(contract)..."
@SAVE_DEPLOYMENTS=1 forge script scripts/deployments/$(if $(findstring facet,$(type)),facets/)${contract}.s.sol:${contract} --ffi --rpc-url sepolia --private-key ${TESTNET_PRIVATE_KEY} --broadcast --verify -vvvv
@SAVE_DEPLOYMENTS=1 forge script scripts/deployments/$(if $(findstring facet,$(type)),facets/)${contract}.s.sol:${contract} --ffi --rpc-url sepolia --private-key ${TESTNET_PRIVATE_KEY} --broadcast --verify --legacy -vvvv

verify-etherscan-sepolia :;
@forge verify-contract ${address} ${contract} --chain sepolia --verifier-url ${ETHERSCAN_SEPOLIA_URL} --etherscan-api-key ${ETHERSCAN_API_KEY}
Expand Down Expand Up @@ -147,7 +147,7 @@ verify-blockscout-base :;
# ===========================

deploy-mainnet :;
@SAVE_DEPLOYMENTS=1 forge script scripts/deployments/$(if $(findstring facet,$(type)),facets/)${contract}.s.sol:${contract} --ffi --rpc-url mainnet --private-key ${TESTNET_PRIVATE_KEY} --broadcast --verify -vvvv
@SAVE_DEPLOYMENTS=1 forge script scripts/deployments/$(if $(findstring facet,$(type)),facets/)${contract}.s.sol:${contract} --ledger --hd-paths "m/44'/60'/1'/0/0" --sender ${PRODUCTION_ADDRESS} --ffi --rpc-url mainnet --broadcast --verify --legacy -vvvv

verify-mainnet :;
@forge verify-contract ${address} ${contract} --chain mainnet
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,28 @@ pragma solidity ^0.8.23;

//contracts
import {Deployer} from "../common/Deployer.s.sol";
import {ProxyDelegation} from "contracts/src/tokens/river/mainnet/delegation/ProxyDelegation.sol";
import {ProxyBatchDelegation} from "contracts/src/tokens/river/mainnet/delegation/ProxyBatchDelegation.sol";

// deployments
import {DeployRiverMainnet} from "./DeployRiverMainnet.s.sol";
import {DeployAuthorizedClaimers} from "./DeployAuthorizedClaimers.s.sol";
import {DeployBaseRegistry} from "contracts/scripts/deployments/DeployBaseRegistry.s.sol";

import {MockMessenger} from "contracts/test/mocks/MockMessenger.sol";

contract DeployProxyDelegation is Deployer {
contract DeployProxyBatchDelegation is Deployer {
// Mainnet
DeployRiverMainnet internal riverHelper = new DeployRiverMainnet();
DeployAuthorizedClaimers internal claimersHelper =
new DeployAuthorizedClaimers();

// Base
DeployBaseRegistry internal deployBaseRegistry = new DeployBaseRegistry();

address public riverToken;
address public claimers;
address public mainnetDelegation;
address public messenger;
address public vault;

function versionName() public pure override returns (string memory) {
return "proxyDelegation";
return "proxyBatchDelegation";
}

function setDependencies(
Expand All @@ -53,7 +49,7 @@ contract DeployProxyDelegation is Deployer {
vm.broadcast(deployer);
messenger = address(new MockMessenger());
} else {
messenger = _getMessenger();
messenger = getMessenger();
}
}

Expand All @@ -64,7 +60,12 @@ contract DeployProxyDelegation is Deployer {
vm.broadcast(deployer);
return
address(
new ProxyDelegation(riverToken, claimers, messenger, mainnetDelegation)
new ProxyBatchDelegation(
riverToken,
claimers,
messenger,
mainnetDelegation
)
);
}

Expand All @@ -74,10 +75,15 @@ contract DeployProxyDelegation is Deployer {
return 0x08cC41b782F27d62995056a4EF2fCBAe0d3c266F;
}

if (block.chainid == 1) {
// Base Registry contract on Base
return 0x7c0422b31401C936172C897802CF0373B35B7698;
}

return getDeployment("baseRegistry");
}

function _getMessenger() internal view returns (address) {
function getMessenger() public view returns (address) {
// Base or Base (Sepolia)
if (block.chainid == 8453 || block.chainid == 84532) {
return 0x4200000000000000000000000000000000000007;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ contract DeployMainnetDelegation is FacetHelper, Deployer {
addSelector(MainnetDelegation.getDelegatedStakeByOperator.selector);
addSelector(MainnetDelegation.setAuthorizedClaimer.selector);
addSelector(MainnetDelegation.getAuthorizedClaimer.selector);
addSelector(MainnetDelegation.setBatchDelegation.selector);
addSelector(MainnetDelegation.getProxyDelegation.selector);
addSelector(MainnetDelegation.getMessenger.selector);
}

function initializer() public pure override returns (bytes4) {
Expand Down
9 changes: 5 additions & 4 deletions contracts/scripts/interactions/InteractPostDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,28 @@ import {DeploySpaceOwner} from "contracts/scripts/deployments/DeploySpaceOwner.s
import {DeploySpaceFactory} from "contracts/scripts/deployments/DeploySpaceFactory.s.sol";
import {DeployBaseRegistry} from "contracts/scripts/deployments/DeployBaseRegistry.s.sol";
import {DeployRiverBase} from "contracts/scripts/deployments/DeployRiverBase.s.sol";
import {DeployProxyDelegation} from "contracts/scripts/deployments/DeployProxyDelegation.s.sol";
import {DeployProxyBatchDelegation} from "contracts/scripts/deployments/DeployProxyBatchDelegation.s.sol";

contract InteractPostDeploy is Interaction {
DeploySpaceOwner deploySpaceOwner = new DeploySpaceOwner();
DeploySpaceFactory deploySpaceFactory = new DeploySpaceFactory();
DeployBaseRegistry deployBaseRegistry = new DeployBaseRegistry();
DeployRiverBase deployRiverBaseToken = new DeployRiverBase();
DeployProxyDelegation deployProxyDelegation = new DeployProxyDelegation();
DeployProxyBatchDelegation deployProxyDelegation =
new DeployProxyBatchDelegation();

function __interact(address deployer) public override {
address spaceOwner = deploySpaceOwner.deploy();
address spaceFactory = deploySpaceFactory.deploy();
address baseRegistry = deployBaseRegistry.deploy();
address riverBaseToken = deployRiverBaseToken.deploy();
// address mainnetProxyDelegation = deployProxyDelegation.deploy();
address mainnetProxyDelegation = deployProxyDelegation.deploy();

vm.startBroadcast(deployer);
ISpaceOwner(spaceOwner).setFactory(spaceFactory);
IImplementationRegistry(spaceFactory).addImplementation(baseRegistry);
SpaceDelegationFacet(baseRegistry).setRiverToken(riverBaseToken);
// IMainnetDelegation(baseRegistry).setProxyDelegation(mainnetProxyDelegation);
IMainnetDelegation(baseRegistry).setProxyDelegation(mainnetProxyDelegation);
vm.stopBroadcast();
}
}
14 changes: 14 additions & 0 deletions contracts/src/tokens/river/base/delegation/IMainnetDelegation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ interface IMainnetDelegationBase {
}

interface IMainnetDelegation is IMainnetDelegationBase {
/**
* @notice Set batch cross-chain delegation
* @param delegators The delegator address
* @param delegates The address the delegator is delegating to
* @param claimers The address the delegator is allowing to claim
* @param quantities The quantity to delegate
*/
function setBatchDelegation(
address[] calldata delegators,
address[] calldata delegates,
address[] calldata claimers,
uint256[] calldata quantities
) external;

/**
* @notice Set delegation of a delegator to a operator
* @param delegator The delegator address
Expand Down
35 changes: 32 additions & 3 deletions contracts/src/tokens/river/base/delegation/MainnetDelegation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pragma solidity ^0.8.23;
// interfaces
import {IMainnetDelegation} from "contracts/src/tokens/river/base/delegation/IMainnetDelegation.sol";
import {ICrossDomainMessenger} from "contracts/src/tokens/river/mainnet/delegation/ICrossDomainMessenger.sol";
import {IProxyDelegation} from "contracts/src/tokens/river/mainnet/delegation/IProxyDelegation.sol";

// libraries

Expand Down Expand Up @@ -48,11 +47,41 @@ contract MainnetDelegation is
}

// =============================================================
// Delegation
// Getters
// =============================================================
function getMessenger() external view returns (address) {
return address(_getMessenger());
}

function getProxyDelegation() external view returns (address) {
return address(_getProxyDelegation());
}

// =============================================================
// Batch Delegation
// =============================================================
function setBatchDelegation(
address[] calldata delegators,
address[] calldata delegates,
address[] calldata claimers,
uint256[] calldata quantities
) external onlyCrossDomainMessenger {
uint256 delegatorsLen = delegators.length;
for (uint256 i; i < delegatorsLen; i++) {
_replaceDelegation(
delegators[i],
claimers[i],
delegates[i],
quantities[i]
);
}
}

// =============================================================
// Delegation
// =============================================================
function setProxyDelegation(address proxyDelegation) external onlyOwner {
_setProxyDelegation(IProxyDelegation(proxyDelegation));
_setProxyDelegation(proxyDelegation);
}

/// @inheritdoc IMainnetDelegation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity ^0.8.23;

// interfaces
import {IMainnetDelegationBase} from "./IMainnetDelegation.sol";
import {IProxyDelegation} from "contracts/src/tokens/river/mainnet/delegation/IProxyDelegation.sol";
import {ICrossDomainMessenger} from "contracts/src/tokens/river/mainnet/delegation/ICrossDomainMessenger.sol";

// libraries
Expand All @@ -15,6 +14,47 @@ import {MainnetDelegationStorage} from "./MainnetDelegationStorage.sol";
abstract contract MainnetDelegationBase is IMainnetDelegationBase {
using EnumerableSet for EnumerableSet.AddressSet;

function _replaceDelegation(
address delegator,
address claimer,
address operator,
uint256 quantity
) internal {
MainnetDelegationStorage.Layout storage ds = MainnetDelegationStorage
.layout();
Delegation storage delegation = ds.delegationByDelegator[delegator];
address currentClaimer = ds.claimerByDelegator[delegator];

// Remove the current delegation if it exists
if (delegation.operator != address(0)) {
ds.delegatorsByOperator[delegation.operator].remove(delegator);

if (
ds.delegatorsByAuthorizedClaimer[currentClaimer].contains(delegator)
) {
ds.delegatorsByAuthorizedClaimer[currentClaimer].remove(delegator);
}
}

// Set the new delegation
ds.delegatorsByOperator[operator].add(delegator);
ds.delegationByDelegator[delegator] = Delegation(
operator,
quantity,
delegator,
block.timestamp
);

// Update the claimer if it has changed
if (claimer != currentClaimer) {
if (currentClaimer != address(0)) {
ds.delegatorsByAuthorizedClaimer[currentClaimer].remove(delegator);
}
ds.claimerByDelegator[delegator] = claimer;
ds.delegatorsByAuthorizedClaimer[claimer].add(delegator);
}
}

function _setDelegation(
address delegator,
address operator,
Expand Down Expand Up @@ -110,11 +150,11 @@ abstract contract MainnetDelegationBase is IMainnetDelegationBase {
return MainnetDelegationStorage.layout().claimerByDelegator[owner];
}

function _setProxyDelegation(IProxyDelegation proxyDelegation) internal {
function _setProxyDelegation(address proxyDelegation) internal {
MainnetDelegationStorage.layout().proxyDelegation = proxyDelegation;
}

function _getProxyDelegation() internal view returns (IProxyDelegation) {
function _getProxyDelegation() internal view returns (address) {
return MainnetDelegationStorage.layout().proxyDelegation;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ library MainnetDelegationStorage {
mapping(address operator => EnumerableSet.AddressSet) delegatorsByOperator;
mapping(address delegator => IMainnetDelegationBase.Delegation delegation) delegationByDelegator;
mapping(address delegator => address claimer) claimerByDelegator;
IProxyDelegation proxyDelegation;
IProxyDelegation deprecatedproxyDelegation; // Do not use this, use proxyDelegation
ICrossDomainMessenger messenger;
mapping(address claimer => EnumerableSet.AddressSet delegators) delegatorsByAuthorizedClaimer;
address proxyDelegation;
}

function layout() internal pure returns (Layout storage s) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,57 @@ pragma solidity ^0.8.23;
// contracts

interface ICrossDomainMessenger {
function xDomainMessageSender() external view returns (address);
event FailedRelayedMessage(bytes32 indexed msgHash);
event RelayedMessage(bytes32 indexed msgHash);
event SentMessage(
address indexed target,
address sender,
bytes message,
uint256 messageNonce,
uint256 gasLimit
);
event SentMessageExtension1(address indexed sender, uint256 value);

function MESSAGE_VERSION() external view returns (uint16);

function MIN_GAS_CALLDATA_OVERHEAD() external view returns (uint64);

function MIN_GAS_CONSTANT_OVERHEAD() external view returns (uint64);

function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()
external
view
returns (uint64);

function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() external view returns (uint64);

function OTHER_MESSENGER() external view returns (address);

function baseGas(
bytes memory _message,
uint32 _minGasLimit
) external pure returns (uint64);

function failedMessages(bytes32) external view returns (bool);

function messageNonce() external view returns (uint256);

function relayMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _minGasLimit,
bytes memory _message
) external payable;

function sendMessage(
address target,
bytes calldata message,
uint32 gasLimit
) external;
address _target,
bytes memory _message,
uint32 _minGasLimit
) external payable;

function successfulMessages(bytes32) external view returns (bool);

function xDomainMessageSender() external view returns (address);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

// interfaces

// libraries

// contracts

interface IProxyBatchDelegation {
function sendDelegators() external;
}
Loading

0 comments on commit ed8f157

Please sign in to comment.