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

Add xcaller #39

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ out/
# Test JS Scripts
test/**/node_modules
test/**/package-lock.json
lib/solmate
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
[submodule "lib/interfaces"]
path = lib/interfaces
url = https://github.com/connext/interfaces
77 changes: 26 additions & 51 deletions contracts/GIVbacksRelayer.sol
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;

import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./interfaces/IGIVBacksRelayer.sol";
import '@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import './interfaces/IGIVBacksRelayer.sol';
import './interfaces/IDistro.sol';

contract GIVbacksRelayer is
Initializable,
AccessControlEnumerableUpgradeable,
IGIVBacksRelayer
{
contract GIVbacksRelayer is Initializable, AccessControlEnumerableUpgradeable, IGIVBacksRelayer {
///
/// CONSTANTS:
///

/// @dev BATCHER_ROLE = keccak256("BATCHER_ROLE");
bytes32 public constant BATCHER_ROLE =
0xeccb356c360bf90186ea17a138ef77420582d0f2a31f7c029d6ae4c3a7c2e186;
bytes32 public constant BATCHER_ROLE = 0xeccb356c360bf90186ea17a138ef77420582d0f2a31f7c029d6ae4c3a7c2e186;

///
/// STORAGE:
Expand All @@ -38,10 +33,7 @@ contract GIVbacksRelayer is

/// @dev Revert if not called by `BATCHER_ROLE`
modifier onlyBatcher() {
require(
hasRole(BATCHER_ROLE, msg.sender),
"GIVBacksRelayer::onlyBatcher: MUST_BATCHER"
);
require(hasRole(BATCHER_ROLE, msg.sender), 'GIVBacksRelayer::onlyBatcher: MUST_BATCHER');
_;
}

Expand All @@ -53,19 +45,9 @@ contract GIVbacksRelayer is
* @param _tokenDistroContract - The address of the TokenDistro
* @param batcher - Initial batcher address
*/
function initialize(
address _tokenDistroContract,
address batcher,
address batcherRoleAdmin
) public initializer {
require(
_tokenDistroContract != address(0),
"GIVBacksRelayer::initialize: NO_TOKENDISTRO_ZERO_ADDRESS"
);
require(
batcher != address(0),
"GIVBacksRelayer::initialize: NO_BATCHER_ZERO_ADDRESS"
);
function initialize(address _tokenDistroContract, address batcher, address batcherRoleAdmin) public initializer {
require(_tokenDistroContract != address(0), 'GIVBacksRelayer::initialize: NO_TOKENDISTRO_ZERO_ADDRESS');
require(batcher != address(0), 'GIVBacksRelayer::initialize: NO_BATCHER_ZERO_ADDRESS');

tokenDistroContract = _tokenDistroContract;

Expand All @@ -80,28 +62,20 @@ contract GIVbacksRelayer is
}

/// @inheritdoc IGIVBacksRelayer
function addBatches(bytes32[] calldata batches, bytes calldata ipfsData)
external
override
onlyBatcher
{
function addBatches(bytes32[] calldata batches, bytes calldata ipfsData) external override onlyBatcher {
for (uint256 i = 0; i < batches.length; i++) {
_addBatch(batches[i], ipfsData);
}
}

/// @inheritdoc IGIVBacksRelayer
function executeBatch(
uint256 _nonce,
address[] calldata recipients,
uint256[] calldata amounts
) external override {
function executeBatch(uint256 _nonce, address[] calldata recipients, uint256[] calldata amounts)
external
override
{
bytes32 h = _hashBatch(_nonce, recipients, amounts);

require(
pendingBatches[h],
"GIVBacksRelayer::executeBatch: NOT_PENDING"
);
require(pendingBatches[h], 'GIVBacksRelayer::executeBatch: NOT_PENDING');

pendingBatches[h] = false;
IDistro(tokenDistroContract).sendGIVbacks(recipients, amounts);
Expand All @@ -114,11 +88,12 @@ contract GIVbacksRelayer is
///

/// @inheritdoc IGIVBacksRelayer
function hashBatch(
uint256 _nonce,
address[] calldata recipients,
uint256[] calldata amounts
) external pure override returns (bytes32) {
function hashBatch(uint256 _nonce, address[] calldata recipients, uint256[] calldata amounts)
external
pure
override
returns (bytes32)
{
return _hashBatch(_nonce, recipients, amounts);
}

Expand All @@ -137,11 +112,11 @@ contract GIVbacksRelayer is
emit AddedBatch(msg.sender, nonce++, batch, ipfsData);
}

function _hashBatch(
uint256 _nonce,
address[] calldata recipients,
uint256[] calldata amounts
) internal pure returns (bytes32) {
function _hashBatch(uint256 _nonce, address[] calldata recipients, uint256[] calldata amounts)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(_nonce, recipients, amounts));
}
}
102 changes: 102 additions & 0 deletions contracts/GivethXCaller.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;

import {IConnext} from '@connext/interfaces/core/IConnext.sol';
import '@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';

contract GivethXCaller is Initializable, AccessControlEnumerableUpgradeable {
IConnext public connext;
bytes32 public CALLER_ROLE = keccak256('CALLER_ROLE');
address public delegate;
address private transferToken;

event ReceiverAdded(uint256 index, string name, address indexed receiver, uint32 indexed domainId);
event AddBatchesSent(address to, uint32 domainId, bytes callData);
event MintNiceSent(address to, uint32 domainId, bytes callData);
event ReceivedModified(uint256 index, address indexed receiver, uint32 indexed domainId);
event AssetTokenSet(address indexed tokenAddress);
event ConnextSet(address indexed connext);
event DelegateSet(address indexed delegate);

struct Receiver {
address to;
uint32 domainId;
}

Receiver[] public receivers;

function initialize(address _connext, address _delegate, address _transferToken) public initializer {
connext = IConnext(_connext);
delegate = _delegate;
transferToken = _transferToken;
__AccessControlEnumerable_init();
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(CALLER_ROLE, msg.sender);
}

function xAddBatches(uint256 receiverIndex, bytes calldata _callData, uint256 _relayerFee)
external payable
onlyRole(CALLER_ROLE)
{
connext.xcall{value: _relayerFee}(
receivers[receiverIndex].domainId,
receivers[receiverIndex].to,
transferToken,
delegate,
0,
3,
_callData
);
emit AddBatchesSent(receivers[receiverIndex].to, receivers[receiverIndex].domainId, _callData);
}

function xMintNice(uint256 receiverIndex, bytes calldata _callData, uint256 _relayerFee)
external payable
onlyRole(CALLER_ROLE)
{
connext.xcall{value: _relayerFee}(
receivers[receiverIndex].domainId,
receivers[receiverIndex].to,
transferToken,
delegate,
0,
3,
_callData
);
emit MintNiceSent(receivers[receiverIndex].to, receivers[receiverIndex].domainId,_callData);
}

function addReceiver(address _to, uint32 _domainId, string memory receiverName)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
receivers.push(Receiver(_to, _domainId));
emit ReceiverAdded(receivers.length - 1, receiverName, _to, _domainId);
}

function modifyReceiver(uint256 _index, address _to, uint32 _domainId) external onlyRole(DEFAULT_ADMIN_ROLE) {
receivers[_index].to = _to;
receivers[_index].domainId = _domainId;
emit ReceivedModified(_index, _to, _domainId);
}

function getReceiverData(uint256 _index) external view returns (address, uint32) {
return (receivers[_index].to, receivers[_index].domainId);
}

function setAssetToken(address tokenAddress) external onlyRole(DEFAULT_ADMIN_ROLE) {
transferToken = tokenAddress;
emit AssetTokenSet(tokenAddress);
}

function setConnect(address _connext) external onlyRole(DEFAULT_ADMIN_ROLE) {
connext = IConnext(_connext);
emit ConnextSet(_connext);
}

function setDelegate(address _delegate) external onlyRole(DEFAULT_ADMIN_ROLE) {
delegate = _delegate;
emit DelegateSet(_delegate);
}
}
74 changes: 74 additions & 0 deletions contracts/GivethXReceiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;

import {IXReceiver} from '@connext/interfaces/core/IXReceiver.sol';
import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';

contract GivethXReceiver is Initializable, OwnableUpgradeable {
address public connext;
address public callerAddress;
uint32 public callerDomainId;
address public target;

event GivbacksRelayerSet(address indexed target);
event ForwardedCall(address target, bytes callData);
event CallerAddressSet(address indexed callerAddress);
event CallerDomainIdSet(uint32 indexed callerDomainId);
event ConnextSet(address indexed connext);


function initialize(address _connext, address _callerAddress, uint32 _callerDomainId, address _target)
public
initializer
{
connext = _connext;
callerAddress = _callerAddress;
callerDomainId = _callerDomainId;
target = _target;
__Ownable_init();
}

modifier onlySource(address _originSender, uint32 _originDomain) {
require(
msg.sender == connext && _originSender == callerAddress && _originDomain == callerDomainId,
'GivethXReceiver: only source'
);
_;
}

function xReceive(
bytes32 _transferId,
uint256 _amount,
address _asset,
address _originSender,
uint32 _origin,
bytes memory _callData
) external onlySource(_originSender, _origin) returns (bool) {
// Unpack the _callData
(bool success,) = target.call(_callData);
require(success, 'Call to target contract failed');
emit ForwardedCall(target, _callData);
return true;
}

function setCallerAddress(address _callerAddress) external onlyOwner {
callerAddress = _callerAddress;
emit CallerAddressSet(_callerAddress);
}

function setCallerDomainId(uint32 _callerDomainId) external onlyOwner {
callerDomainId = _callerDomainId;
emit CallerDomainIdSet(_callerDomainId);
}

function setGivbacksRelayer(address _target) external onlyOwner {
target = _target;
emit GivbacksRelayerSet(_target);
}

function setConnext(address _connext) external onlyOwner {
connext = _connext;
emit ConnextSet(_connext);
}
}
2 changes: 1 addition & 1 deletion contracts/UnipoolGIVpower.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity =0.8.10;
pragma solidity ^0.8.10;

import '@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol';
import 'solmate/utils/FixedPointMathLib.sol';
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IDistro.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity =0.8.10;
pragma solidity ^0.8.10;

interface IDistro {
/**
Expand Down
15 changes: 5 additions & 10 deletions contracts/interfaces/IGIVBacksRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,7 @@ interface IGIVBacksRelayer {
* @param recipients - Parameter passed
* @param amounts - Parameter passed
*/
function executeBatch(
uint256 _nonce,
address[] calldata recipients,
uint256[] calldata amounts
) external;
function executeBatch(uint256 _nonce, address[] calldata recipients, uint256[] calldata amounts) external;

/**
* @dev This function will produce a hash of parameters for the
Expand All @@ -90,11 +86,10 @@ interface IGIVBacksRelayer {
* @param amounts - Parameter passed
* @return The batch hash
*/
function hashBatch(
uint256 _nonce,
address[] calldata recipients,
uint256[] calldata amounts
) external pure returns (bytes32);
function hashBatch(uint256 _nonce, address[] calldata recipients, uint256[] calldata amounts)
external
pure
returns (bytes32);

/**
* @dev This function will return the pending status of a batch.
Expand Down
8 changes: 6 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
src = 'contracts'
out = 'out'
fuzz_runs = 5000
auto_detect_solc = true
libs = ['lib']
remappings = [
'ds-test/=lib/forge-std/lib/ds-test/src/',
'forge-std/=lib/forge-std/src/',
'solmate/=lib/solmate/src/',
'@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/',
'@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/'
'@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/',
'@connext/interfaces/=lib/interfaces/',
'aragon-apps/=lib/aragon-apps/apps/',

]
[rpc_endpoints]
optimism="${OPTIMISIM_RPC_URL}"
Expand All @@ -17,4 +21,4 @@ optimism="${OPTIMISIM_RPC_URL}"
line_length = 120
quote_style = 'single'

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
1 change: 1 addition & 0 deletions lib/interfaces
Submodule interfaces added at 2e0287
Loading