Skip to content
2 changes: 1 addition & 1 deletion deployments/v2.1/scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

forge script ./script/RouterAndApprovalProxyV2_1Deployer.s.sol:RouterAndApprovalProxyV2_1Deployer \
forge script ./script/v2.1/RouterAndApprovalProxyV2_1Deployer.s.sol:RouterAndApprovalProxyV2_1Deployer \
--slow \
--broadcast \
--private-key $DEPLOYER_PK \
Expand Down
2 changes: 1 addition & 1 deletion deployments/v2.1/scripts/deploy_non_tstore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

export FOUNDRY_PROFILE=london

forge script ./script/RouterAndApprovalProxyV2_1_NonTstore_Deployer.s.sol:RouterAndApprovalProxyV2_1_NonTstore_Deployer \
forge script ./script/v2.1/RouterAndApprovalProxyV2_1_NonTstore_Deployer.s.sol:RouterAndApprovalProxyV2_1_NonTstore_Deployer \
--slow \
--broadcast \
--contracts ./src/v2.1/Relay \
Expand Down
13 changes: 13 additions & 0 deletions deployments/v3/addresses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"name": "base",
"chainId": 8453,
"compilerVersion": "0.8.28",
"evmVersion": "cancun",
"explorerUrl": "https://basescan.org",
"relayRouter": "0x82603d1713b410337d8a84dcad1f645fdf1463b4",
"relayApprovalProxy": "0x2ed919ca59bfd6ff2093f31c640c2f8bff031f14",
"create2Factory": "0x4e59b44847b379578588920ca78fbf26c0b4956c",
"permit2": "0x000000000022d473030f116ddee9f6b43ac78ba3"
}
]
7 changes: 7 additions & 0 deletions deployments/v3/scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

forge script ./script/v3/RouterAndApprovalProxyV3Deployer.s.sol:RouterAndApprovalProxyV3Deployer \
--slow \
--broadcast \
--private-key $DEPLOYER_PK \
--create2-deployer $CREATE2_FACTORY
17 changes: 17 additions & 0 deletions deployments/v3/scripts/verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# Get the verification flags from the deployment file
VERIFICATION_FLAGS=$(jq -c ".[] | select(.name == \"$CHAIN\") | .verificationFlags" "./deployments/$DEPLOYMENT_FILE")

if [ "$VERIFICATION_FLAGS" != "null" ]; then
# Split the verification flags into an array
expanded_verification_flags=(`echo $VERIFICATION_FLAGS | tr -d '"'`)

# Verify the contracts using the above flags
forge verify-contract ${expanded_verification_flags[@]} $RELAY_ROUTER ./src/v3/RelayRouterV3.sol:RelayRouterV3
forge verify-contract ${expanded_verification_flags[@]} $RELAY_APPROVAL_PROXY ./src/v3/RelayApprovalProxyV3.sol:RelayApprovalProxyV3 --constructor-args $(cast abi-encode "constructor(address, address, address)" $DEPLOYER_ADDRESS $RELAY_ROUTER $PERMIT2)
else
# Verify the contracts
forge verify-contract --chain $CHAIN $RELAY_ROUTER ./src/v3/RelayRouterV3.sol:RelayRouterV3
forge verify-contract --chain $CHAIN $RELAY_APPROVAL_PROXY ./src/v3/RelayApprovalProxyV3.sol:RelayApprovalProxyV3 --constructor-args $(cast abi-encode "constructor(address, address, address)" $DEPLOYER_ADDRESS $RELAY_ROUTER $PERMIT2)
fi
20 changes: 20 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"lib/0x-settler": {
"rev": "2051c492f0350acb7b50118248c2afe24274a5ac"
},
"lib/forge-std": {
"rev": "1714bee72e286e73f76e320d110e0eaf5c4e649d"
},
"lib/openzeppelin-contracts": {
"rev": "dbb6104ce834628e473d2173bbc9d47f81a9eec3"
},
"lib/permit2-relay": {
"rev": "c4c481b643849db988d2f08610f37da7efcd2bda"
},
"lib/solady": {
"rev": "f74d6b6cec7e5f72f57949dfa5d51b632bcc29a6"
},
"lib/trustlessPermit": {
"rev": "07a51a046580c5a6c7bb71cbf4cf6738e85ab310"
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import "forge-std/Script.sol";
import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

import {RelayApprovalProxyV2_1} from "../src/v2.1/RelayApprovalProxyV2_1.sol";
import {RelayRouterV2_1} from "../src/v2.1/RelayRouterV2_1.sol";
import {RelayApprovalProxyV2_1} from "../../src/v2.1/RelayApprovalProxyV2_1.sol";
import {RelayRouterV2_1} from "../../src/v2.1/RelayRouterV2_1.sol";

contract RouterAndApprovalProxyV2_1Deployer is Script {
// Thrown when the predicted address doesn't match the deployed address
Expand Down Expand Up @@ -47,7 +47,9 @@ contract RouterAndApprovalProxyV2_1Deployer is Script {
create2Factory,
SALT,
keccak256(
abi.encodePacked(type(RelayRouterV2_1).creationCode)
abi.encodePacked(
type(RelayRouterV2_1).creationCode
)
)
)
)
Expand All @@ -68,10 +70,7 @@ contract RouterAndApprovalProxyV2_1Deployer is Script {

// Ensure the predicted and actual addresses match
if (predictedAddress != address(router)) {
revert IncorrectContractAddress(
predictedAddress,
address(router)
);
revert IncorrectContractAddress(predictedAddress, address(router));
}

console2.log("RelayRouterV2_1 deployed");
Expand Down Expand Up @@ -106,7 +105,10 @@ contract RouterAndApprovalProxyV2_1Deployer is Script {
)
);

console2.log("Predicted address for RelayApprovalProxyV2_1", predictedAddress);
console2.log(
"Predicted address for RelayApprovalProxyV2_1",
predictedAddress
);

// Verify if the contract has already been deployed
if (_hasBeenDeployed(predictedAddress)) {
Expand All @@ -115,11 +117,9 @@ contract RouterAndApprovalProxyV2_1Deployer is Script {
}

// Deploy
RelayApprovalProxyV2_1 approvalProxy = new RelayApprovalProxyV2_1{salt: SALT}(
msg.sender,
router,
permit2
);
RelayApprovalProxyV2_1 approvalProxy = new RelayApprovalProxyV2_1{
salt: SALT
}(msg.sender, router, permit2);

// Ensure the predicted and actual addresses match
if (predictedAddress != address(approvalProxy)) {
Expand All @@ -143,4 +143,4 @@ contract RouterAndApprovalProxyV2_1Deployer is Script {
}
return (size > 0);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import "forge-std/Script.sol";
import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

import {RelayApprovalProxyV2_1} from "../src/v2.1/RelayApprovalProxyV2_1.sol";
import {RelayRouterV2_1_NonTstore} from "../src/v2.1/RelayRouterV2_1_NonTstore.sol";
import {RelayApprovalProxyV2_1} from "../../src/v2.1/RelayApprovalProxyV2_1.sol";
import {RelayRouterV2_1_NonTstore} from "../../src/v2.1/RelayRouterV2_1_NonTstore.sol";

contract RouterAndApprovalProxyV2_1_NonTstore_Deployer is Script {
// Thrown when the predicted address doesn't match the deployed address
Expand Down
145 changes: 145 additions & 0 deletions script/v3/RouterAndApprovalProxyV3Deployer.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {Script} from "forge-std/Script.sol";
import {console2} from "forge-std/console2.sol";

import {RelayApprovalProxyV3} from "../../src/v3/RelayApprovalProxyV3.sol";
import {RelayRouterV3} from "../../src/v3/RelayRouterV3.sol";

contract RouterAndApprovalProxyV3Deployer is Script {
// Thrown when the predicted address doesn't match the deployed address
error IncorrectContractAddress(address predicted, address actual);

// Modify for vanity address generation
bytes32 public SALT = bytes32(uint256(1));

function setUp() public {}

function run() public {
vm.createSelectFork(vm.envString("CHAIN"));

vm.startBroadcast();

RelayRouterV3 router = RelayRouterV3(payable(deployRouter()));
RelayApprovalProxyV3 approvalProxy = RelayApprovalProxyV3(
payable(deployApprovalProxy(address(router)))
);

assert(approvalProxy.owner() == msg.sender);

vm.stopBroadcast();
}

function deployRouter() public returns (address) {
console2.log("Deploying RelayRouterV3");

address create2Factory = vm.envAddress("CREATE2_FACTORY");

// Compute predicted address
address predictedAddress = address(
uint160(
uint(
keccak256(
abi.encodePacked(
bytes1(0xff),
create2Factory,
SALT,
keccak256(
abi.encodePacked(
type(RelayRouterV3).creationCode
)
)
)
)
)
)
);

console2.log("Predicted address for RelayRouterV3", predictedAddress);

// Verify if the contract has already been deployed
if (_hasBeenDeployed(predictedAddress)) {
console2.log("RelayRouterV3 was already deployed");
return predictedAddress;
}

// Deploy
RelayRouterV3 router = new RelayRouterV3{salt: SALT}();

// Ensure the predicted and actual addresses match
if (predictedAddress != address(router)) {
revert IncorrectContractAddress(predictedAddress, address(router));
}

console2.log("RelayRouterV3 deployed");

return address(router);
}

function deployApprovalProxy(address router) public returns (address) {
console2.log("Deploying ApprovalProxyV3");

address create2Factory = vm.envAddress("CREATE2_FACTORY");
address permit2 = vm.envAddress("PERMIT2");

// Compute predicted address
address predictedAddress = address(
uint160(
uint(
keccak256(
abi.encodePacked(
bytes1(0xff),
create2Factory,
SALT,
keccak256(
abi.encodePacked(
type(RelayApprovalProxyV3).creationCode,
abi.encode(msg.sender, router, permit2)
)
)
)
)
)
)
);

console2.log(
"Predicted address for RelayApprovalProxyV3",
predictedAddress
);

// Verify if the contract has already been deployed
if (_hasBeenDeployed(predictedAddress)) {
console2.log("RelayApprovalProxyV3 was already deployed");
return predictedAddress;
}

// Deploy
RelayApprovalProxyV3 approvalProxy = new RelayApprovalProxyV3{
salt: SALT
}(msg.sender, router, permit2);

// Ensure the predicted and actual addresses match
if (predictedAddress != address(approvalProxy)) {
revert IncorrectContractAddress(
predictedAddress,
address(approvalProxy)
);
}

console2.log("RelayApprovalProxyV3 deployed");

return address(approvalProxy);
}

function _hasBeenDeployed(
address addressToCheck
) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(addressToCheck)
}
return (size > 0);
}
}
File renamed without changes.
12 changes: 11 additions & 1 deletion src/v2.1/utils/Multicall3.sol → src/common/Multicall3.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;

import {Call3Value, Result} from "./RelayV2_1Structs.sol";
struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}

struct Result {
bool success;
bytes returnData;
}

/// @title Multicall3
/// @notice Aggregate results from multiple function calls
Expand Down
17 changes: 0 additions & 17 deletions src/v2.1/utils/RelayV2_1Structs.sol → src/common/Permits.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}

struct Permit2612 {
address token;
address owner;
Expand All @@ -28,13 +21,3 @@ struct Permit3009 {
bytes32 r;
bytes32 s;
}

struct Result {
bool success;
bytes returnData;
}

struct RelayerWitness {
address relayer;
Call3Value[] call3Values;
}
6 changes: 3 additions & 3 deletions src/v2.1/RelayApprovalProxyV2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
pragma solidity ^0.8.23;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IPermit2} from "permit2-relay/src/interfaces/IPermit2.sol";
import {ISignatureTransfer} from "permit2-relay/src/interfaces/ISignatureTransfer.sol";
import {Ownable} from "solady/src/auth/Ownable.sol";
import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol";
import {TrustlessPermit} from "trustlessPermit/TrustlessPermit.sol";

import {IERC3009} from "./interfaces/IERC3009.sol";
import {IRelayRouterV2_1} from "./interfaces/IRelayRouterV2_1.sol";
import {Call3Value, Permit2612, Permit3009, Result} from "./utils/RelayV2_1Structs.sol";
import {IERC3009} from "../common/IERC3009.sol";
import {Call3Value, Result} from "../common/Multicall3.sol";
import {Permit2612, Permit3009} from "../common/Permits.sol";

contract RelayApprovalProxyV2_1 is Ownable {
using SafeERC20 for IERC20;
Expand Down
6 changes: 2 additions & 4 deletions src/v2.1/RelayRouterV2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
pragma solidity ^0.8.25;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol";

import {Multicall3} from "./utils/Multicall3.sol";
import {ReentrancyGuardMsgSender} from "./utils/ReentrancyGuardMsgSender.sol";
import {Call3Value, Result, RelayerWitness} from "./utils/RelayV2_1Structs.sol";
import {Call3Value, Multicall3, Result} from "../common/Multicall3.sol";
import {ReentrancyGuardMsgSender} from "../common/ReentrancyGuardMsgSender.sol";

contract RelayRouterV2_1 is Multicall3, ReentrancyGuardMsgSender {
using SafeTransferLib for address;
Expand Down
Loading