Skip to content
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 lib/core
Submodule core updated 373 files
3 changes: 3 additions & 0 deletions script/DeployExecutor.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ contract DeployExecutorScript is DeployExecutorBaseScript {
address public constant REACTOR = 0xC323B898d7E4105E3980082B74CC5D4602996B10;
// Executor owner. Defaults to the sender when left zero.
address public constant ADMIN = 0x0000000000000000000000000000000000000000;
// Owner of the proxy's ProxyAdmin, authorized to upgrade. Defaults to the sender when left zero.
address public constant PROXY_ADMIN_OWNER = 0x0000000000000000000000000000000000000000;
// Initial caller allowed to invoke fill entrypoints. Defaults to the sender when left zero.
address public constant CALLER = 0x0000000000000000000000000000000000000000;

Expand All @@ -21,6 +23,7 @@ contract DeployExecutorScript is DeployExecutorBaseScript {
DeployParams({
reactor: REACTOR,
admin: ADMIN == address(0) ? owner : ADMIN,
proxyAdminOwner: PROXY_ADMIN_OWNER == address(0) ? owner : PROXY_ADMIN_OWNER,
caller: CALLER == address(0) ? owner : CALLER
})
);
Expand Down
34 changes: 34 additions & 0 deletions script/DeployLifiExecutor.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {DeployLifiExecutorBaseScript} from "./deploy/base/DeployLifiExecutorBase.s.sol";

// forge script script/DeployLifiExecutor.s.sol:DeployLifiExecutorScript --rpc-url=RPC --broadcast

contract DeployLifiExecutorScript is DeployLifiExecutorBaseScript {
// Configurations - UPDATE THESE BEFORE DEPLOYMENT

// LI.FI OIF InputSettlerEscrow this executor finalises orders through.
address public constant INPUT_SETTLER = 0x000025c3226C00B2Cdc200005a1600509f4e00C0;
// LI.FI OIF OutputSettler this executor fills and attests outputs through.
address public constant OUTPUT_SETTLER = 0x0000000000eC36B683C2E6AC89e9A75989C22a2e;
// Executor owner. Defaults to the sender when left zero.
address public constant ADMIN = 0x0000000000000000000000000000000000000000;
// Owner of the proxy's ProxyAdmin, authorized to upgrade. Defaults to the sender when left zero.
address public constant PROXY_ADMIN_OWNER = 0x0000000000000000000000000000000000000000;
// Initial caller allowed to invoke finalise and register with LI.FI. Defaults to the sender when left zero.
address public constant CALLER = 0x0000000000000000000000000000000000000000;

function run() public returns (DeploymentData memory data) {
address owner = _scriptOwner();
data = runBase(
DeployParams({
inputSettler: INPUT_SETTLER,
outputSettler: OUTPUT_SETTLER,
admin: ADMIN == address(0) ? owner : ADMIN,
proxyAdminOwner: PROXY_ADMIN_OWNER == address(0) ? owner : PROXY_ADMIN_OWNER,
caller: CALLER == address(0) ? owner : CALLER
})
);
}
}
26 changes: 21 additions & 5 deletions script/deploy/base/DeployExecutorBase.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ pragma solidity ^0.8.28;

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

import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

import {Executor} from "../../../src/Executor.sol";

contract DeployExecutorBaseScript is Script {
struct DeployParams {
address reactor;
address admin;
address proxyAdminOwner;
address caller;
}

struct DeploymentData {
Executor executor;
address implementation;
address reactor;
address admin;
address proxyAdminOwner;
address caller;
}

Expand All @@ -26,11 +31,19 @@ contract DeployExecutorBaseScript is Script {
callers[0] = params.caller;

_startBroadcast();
data.executor = new Executor(params.reactor, params.admin, callers);
Executor implementation = new Executor(params.reactor);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(implementation),
params.proxyAdminOwner,
abi.encodeCall(Executor.initialize, (params.admin, callers))
);
_stopBroadcast();

data.executor = Executor(payable(address(proxy)));
data.implementation = address(implementation);
data.reactor = params.reactor;
data.admin = params.admin;
data.proxyAdminOwner = params.proxyAdminOwner;
data.caller = params.caller;

_validateDeployment(data);
Expand All @@ -53,6 +66,7 @@ contract DeployExecutorBaseScript is Script {
function _validateParams(DeployParams memory params) internal pure {
require(params.reactor != address(0), "invalid reactor");
require(params.admin != address(0), "invalid admin");
require(params.proxyAdminOwner != address(0), "invalid proxy admin owner");
require(params.caller != address(0), "invalid caller");
}

Expand All @@ -63,9 +77,11 @@ contract DeployExecutorBaseScript is Script {

function _logDeployment(DeploymentData memory data) internal view {
console2.log("Deployed RFQ Executor");
console2.log(" executor: ", address(data.executor));
console2.log(" reactor: ", data.reactor);
console2.log(" admin: ", data.admin);
console2.log(" caller: ", data.caller);
console2.log(" executor: ", address(data.executor));
console2.log(" implementation: ", data.implementation);
console2.log(" reactor: ", data.reactor);
console2.log(" admin: ", data.admin);
console2.log(" proxyAdminOwner: ", data.proxyAdminOwner);
console2.log(" caller: ", data.caller);
}
}
94 changes: 94 additions & 0 deletions script/deploy/base/DeployLifiExecutorBase.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

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

import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

import {LiquidLaneLifiExecutor} from "../../../src/lifi/LiquidLaneLifiExecutor.sol";

contract DeployLifiExecutorBaseScript is Script {
struct DeployParams {
address inputSettler;
address outputSettler;
address admin;
address proxyAdminOwner;
address caller;
}

struct DeploymentData {
LiquidLaneLifiExecutor executor;
address implementation;
address inputSettler;
address outputSettler;
address admin;
address proxyAdminOwner;
address caller;
}

function runBase(DeployParams memory params) public virtual returns (DeploymentData memory data) {
_validateParams(params);

address[] memory callers = new address[](1);
callers[0] = params.caller;

_startBroadcast();
LiquidLaneLifiExecutor implementation = new LiquidLaneLifiExecutor(params.inputSettler, params.outputSettler);
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
address(implementation),
params.proxyAdminOwner,
abi.encodeCall(LiquidLaneLifiExecutor.initialize, (params.admin, callers))
);
_stopBroadcast();

data.executor = LiquidLaneLifiExecutor(address(proxy));
data.implementation = address(implementation);
data.inputSettler = params.inputSettler;
data.outputSettler = params.outputSettler;
data.admin = params.admin;
data.proxyAdminOwner = params.proxyAdminOwner;
data.caller = params.caller;

_validateDeployment(data);
_logDeployment(data);
}

function _startBroadcast() internal virtual {
vm.startBroadcast();
}

function _stopBroadcast() internal virtual {
vm.stopBroadcast();
}

function _scriptOwner() internal view virtual returns (address owner_) {
(,, address origin) = vm.readCallers();
owner_ = origin == address(0) ? msg.sender : origin;
}

function _validateParams(DeployParams memory params) internal pure {
require(params.inputSettler != address(0), "invalid input settler");
require(params.outputSettler != address(0), "invalid output settler");
require(params.admin != address(0), "invalid admin");
require(params.proxyAdminOwner != address(0), "invalid proxy admin owner");
require(params.caller != address(0), "invalid caller");
}

function _validateDeployment(DeploymentData memory data) internal view {
assert(data.executor.owner() == data.admin);
assert(data.executor.INPUT_SETTLER() == data.inputSettler);
assert(data.executor.OUTPUT_SETTLER() == data.outputSettler);
assert(data.executor.isCaller(data.caller));
}

function _logDeployment(DeploymentData memory data) internal view {
console2.log("Deployed LI.FI Executor");
console2.log(" executor: ", address(data.executor));
console2.log(" implementation: ", data.implementation);
console2.log(" inputSettler: ", data.inputSettler);
console2.log(" outputSettler: ", data.outputSettler);
console2.log(" admin: ", data.admin);
console2.log(" proxyAdminOwner: ", data.proxyAdminOwner);
console2.log(" caller: ", data.caller);
}
}
15 changes: 12 additions & 3 deletions src/Executor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import {IReactor, NATIVE} from "./interfaces/IReactor.sol";

import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

/// @title Executor
/// @notice Caller-gated executor that forwards fills into Reactor and handles execution callbacks.
contract Executor is Ownable, IExecutor {
/// @dev Deployed behind a transparent proxy; the Reactor address is immutable in the implementation
/// while ownership and the caller list live in proxy storage set by {initialize}.
contract Executor is Initializable, OwnableUpgradeable, IExecutor {
using Address for address payable;
using SafeERC20 for IERC20;
using Address for address;
Expand All @@ -30,8 +33,14 @@ contract Executor is Ownable, IExecutor {

/* CONSTRUCTOR */

constructor(address reactor, address owner, address[] memory initCallers) Ownable(owner) {
constructor(address reactor) {
REACTOR = reactor;
_disableInitializers();
}

/// @inheritdoc IExecutor
function initialize(address owner, address[] calldata initCallers) external initializer {
__Ownable_init(owner);

callers = initCallers;
}
Expand Down
7 changes: 7 additions & 0 deletions src/interfaces/IExecutor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ interface IExecutor {

/* FUNCTIONS */

/**
* @notice Initializes the proxy with its owner and allowed caller list.
* @param owner Owner authorized to manage the caller list.
* @param initCallers Initial addresses allowed to call the fill entrypoints.
*/
function initialize(address owner, address[] calldata initCallers) external;

/**
* @notice Returns an allowed caller by index.
* @param index Caller index.
Expand Down
Loading
Loading