Skip to content
Open
Show file tree
Hide file tree
Changes from 7 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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
[submodule "lib/dynamic-contracts"]
path = lib/dynamic-contracts
url = https://github.com/thirdweb-dev/dynamic-contracts
[submodule "lib/prb-proxy"]
path = lib/prb-proxy
url = https://github.com/PaulRBerg/prb-proxy
251 changes: 251 additions & 0 deletions contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

Check warning

Code scanning / Slither

Different pragma directives are used

Different versions of Solidity are used: - Version used: ['>=0.8.18', '>=0.8.4', '^0.8.0', '^0.8.1', '^0.8.10', '^0.8.11', '^0.8.12', '^0.8.2', '^0.8.4', '^0.8.8', '^0.8.9'] - >=0.8.18 (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#2) - >=0.8.18 (lib/prb-proxy/src/PRBProxy.sol#2) - >=0.8.4 (lib/prb-proxy/src/interfaces/IPRBProxy.sol#2) - >=0.8.4 (lib/prb-proxy/src/interfaces/IPRBProxyPlugin.sol#2) - >=0.8.4 (lib/prb-proxy/src/interfaces/IPRBProxyRegistry.sol#2) - ^0.8.0 (contracts/base/ERC1155Base.sol#2) - ^0.8.0 (contracts/base/ERC1155DelayedReveal.sol#2) - ^0.8.0 (contracts/base/ERC1155Drop.sol#2) - ^0.8.0 (contracts/base/ERC1155LazyMint.sol#2) - ^0.8.0 (contracts/base/ERC1155SignatureMint.sol#2) - ^0.8.0 (contracts/base/ERC20Base.sol#2) - ^0.8.0 (contracts/base/ERC20Drop.sol#2) - ^0.8.0 (contracts/base/ERC20DropVote.sol#2) - ^0.8.0 (contracts/base/ERC20SignatureMint.sol#2) - ^0.8.0 (contracts/base/ERC20SignatureMintVote.sol#2) - ^0.8.0 (contracts/base/ERC20Vote.sol#2) - ^0.8.0 (contracts/base/ERC721Base.sol#2) - ^0.8.0 (contracts/base/ERC721DelayedReveal.sol#2) - ^0.8.0 (contracts/base/ERC721Drop.sol#2) - ^0.8.0 (contracts/base/ERC721LazyMint.sol#2) - ^0.8.0 (contracts/base/ERC721Multiwrap.sol#2) - ^0.8.0 (contracts/base/ERC721SignatureMint.sol#2) - ^0.8.0 (contracts/base/Staking1155Base.sol#2) - ^0.8.0 (contracts/base/Staking20Base.sol#2) - ^0.8.0 (contracts/base/Staking721Base.sol#2) - ^0.8.0 (contracts/eip/ERC1155.sol#2) - ^0.8.0 (contracts/eip/ERC1271.sol#2) - ^0.8.0 (contracts/eip/ERC165.sol#4) - ^0.8.0 (contracts/eip/interface/IERC1155.sol#2) - ^0.8.0 (contracts/eip/interface/IERC1155Enumerable.sol#2) - ^0.8.0 (contracts/eip/interface/IERC1155Metadata.sol#2) - ^0.8.0 (contracts/eip/interface/IERC1155Receiver.sol#4) - ^0.8.0 (contracts/eip/interface/IERC1155Supply.sol#2) - ^0.8.0 (contracts/eip/interface/IERC165.sol#4) - ^0.8.0 (contracts/eip/interface/IERC20.sol#2) - ^0.8.0 (contracts/eip/interface/IERC20Metadata.sol#2) - ^0.8.0 (contracts/eip/interface/IERC20Permit.sol#4) - ^0.8.0 (contracts/eip/interface/IERC2981.sol#2) - ^0.8.0 (contracts/eip/interface/IERC721.sol#4) - ^0.8.0 (contracts/eip/interface/IERC721Enumerable.sol#2) - ^0.8.0 (contracts/eip/interface/IERC721Metadata.sol#2) - ^0.8.0 (contracts/eip/interface/IERC721Receiver.sol#4) - ^0.8.0 (contracts/eip/interface/IERC721Supply.sol#2) - ^0.8.0 (contracts/eip/queryable/ERC721AStorage.sol#3) - ^0.8.0 (contracts/eip/queryable/ERC721A__Initializable.sol#2) - ^0.8.0 (contracts/eip/queryable/ERC721A__InitializableStorage.sol#3) - ^0.8.0 (contracts/extension/AppURI.sol#2) - ^0.8.0 (contracts/extension/BatchMintMetadata.sol#2) - ^0.8.0 (contracts/extension/BurnToClaim.sol#2) - ^0.8.0 (contracts/extension/ContractMetadata.sol#2) - ^0.8.0 (contracts/extension/DelayedReveal.sol#2) - ^0.8.0 (contracts/extension/Drop.sol#2) - ^0.8.0 (contracts/extension/Drop1155.sol#2) - ^0.8.0 (contracts/extension/DropSinglePhase.sol#2) - ^0.8.0 (contracts/extension/DropSinglePhase1155.sol#2) - ^0.8.0 (contracts/extension/Initializable.sol#2) - ^0.8.0 (contracts/extension/LazyMint.sol#2) - ^0.8.0 (contracts/extension/LazyMintWithTier.sol#2) - ^0.8.0 (contracts/extension/Multicall.sol#2) - ^0.8.0 (contracts/extension/NFTMetadata.sol#2) - ^0.8.0 (contracts/extension/OperatorFilterToggle.sol#2) - ^0.8.0 (contracts/extension/OperatorFilterer.sol#2) - ^0.8.0 (contracts/extension/OperatorFiltererUpgradeable.sol#2) - ^0.8.0 (contracts/extension/Ownable.sol#2) - ^0.8.0 (contracts/extension/Permissions.sol#2) - ^0.8.0 (contracts/extension/PermissionsEnumerable.sol#2) - ^0.8.0 (contracts/extension/PlatformFee.sol#2) - ^0.8.0 (contracts/extension/PrimarySale.sol#2) - ^0.8.0 (contracts/extension/Proxy.sol#2) - ^0.8.0 (contracts/extension/ProxyForUpgradeable.sol#2) - ^0.8.0 (contracts/extension/Royalty.sol#2) - ^0.8.0 (contracts/extension/SignatureAction.sol#2) - ^0.8.0 (contracts/extension/SignatureActionUpgradeable.sol#2) - ^0.8.0 (contracts/extension/SignatureMintERC1155.sol#2) - ^0.8.0 (contrac

import { IPRBProxy } from "@prb/proxy/src/interfaces/IPRBProxy.sol";
import { IPRBProxyPlugin } from "@prb/proxy/src/interfaces/IPRBProxyPlugin.sol";
import { IPRBProxyRegistry } from "@prb/proxy/src/interfaces/IPRBProxyRegistry.sol";
import { PRBProxy } from "@prb/proxy/src/PRBProxy.sol";

/// @author Modified from prb-proxy (https://github.com/PaulRBerg/prb-proxy/blob/main/src/PRBProxyRegistry.sol)
/// @title PRBProxyRegistry
/// @dev See the documentation in {IPRBProxyRegistry}.
contract PRBProxyRegistryModified is IPRBProxyRegistry {
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IPRBProxyRegistry
string public constant override VERSION = "4.0.2";

/// @dev Magic value to override target permissions. Holders can execute on any target.
address public constant MAGIC_TARGET = address(0x42);

/*//////////////////////////////////////////////////////////////////////////
USER-FACING STORAGE
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IPRBProxyRegistry
ConstructorParams public override constructorParams;

/*//////////////////////////////////////////////////////////////////////////
INTERNAL STORAGE
//////////////////////////////////////////////////////////////////////////*/

mapping(address owner => mapping(IPRBProxyPlugin plugin => bytes4[] methods)) internal _methods;

mapping(address owner => mapping(address envoy => mapping(address target => bool permission)))
internal _permissions;

mapping(address owner => mapping(bytes4 method => IPRBProxyPlugin plugin)) internal _plugins;

mapping(address owner => IPRBProxy proxy) internal _proxies;

/*//////////////////////////////////////////////////////////////////////////
MODIFIERS
//////////////////////////////////////////////////////////////////////////*/

/// @notice Checks that the caller has a proxy.
modifier onlyCallerWithProxy() {
if (address(_proxies[msg.sender]) == address(0)) {
revert PRBProxyRegistry_UserDoesNotHaveProxy(msg.sender);
}
_;
}

/// @notice Check that the user does not have a proxy.
modifier onlyNonProxyOwner(address user) {
IPRBProxy proxy = _proxies[user];
if (address(proxy) != address(0)) {
revert PRBProxyRegistry_UserHasProxy(user, proxy);
}
_;
}

/*//////////////////////////////////////////////////////////////////////////
USER-FACING CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IPRBProxyRegistry
function getMethodsByOwner(address owner, IPRBProxyPlugin plugin) external view returns (bytes4[] memory methods) {
methods = _methods[owner][plugin];
}

/// @inheritdoc IPRBProxyRegistry
function getMethodsByProxy(
IPRBProxy proxy,
IPRBProxyPlugin plugin
) external view returns (bytes4[] memory methods) {
methods = _methods[proxy.owner()][plugin];
}

/// @inheritdoc IPRBProxyRegistry
function getPermissionByOwner(
address owner,
address envoy,
address target
) external view returns (bool permission) {
permission = _permissions[owner][envoy][target] || _permissions[owner][envoy][MAGIC_TARGET];
}

/// @inheritdoc IPRBProxyRegistry
function getPermissionByProxy(
IPRBProxy proxy,
address envoy,
address target
) external view returns (bool permission) {
permission = _permissions[proxy.owner()][envoy][target] || _permissions[proxy.owner()][envoy][MAGIC_TARGET];
}

/// @inheritdoc IPRBProxyRegistry
function getPluginByOwner(address owner, bytes4 method) external view returns (IPRBProxyPlugin plugin) {
plugin = _plugins[owner][method];
}

/// @inheritdoc IPRBProxyRegistry
function getPluginByProxy(IPRBProxy proxy, bytes4 method) external view returns (IPRBProxyPlugin plugin) {
plugin = _plugins[proxy.owner()][method];
}

/// @inheritdoc IPRBProxyRegistry
function getProxy(address user) external view returns (IPRBProxy proxy) {
proxy = _proxies[user];
}

/*//////////////////////////////////////////////////////////////////////////
USER-FACING NON-CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IPRBProxyRegistry
function deploy() external override onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
proxy = _deploy({ owner: msg.sender, target: address(0), data: "" });
}

/// @inheritdoc IPRBProxyRegistry
function deployAndExecute(
address target,
bytes calldata data
) external override onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
proxy = _deploy({ owner: msg.sender, target: target, data: data });
}

/// @inheritdoc IPRBProxyRegistry
function deployFor(address user) external override onlyNonProxyOwner(user) returns (IPRBProxy proxy) {
proxy = _deploy({ owner: user, target: address(0), data: "" });
}

/// @inheritdoc IPRBProxyRegistry
function deployAndExecuteAndInstallPlugin(
address target,
bytes calldata data,
IPRBProxyPlugin plugin
) external override onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
proxy = _deploy({ owner: msg.sender, target: target, data: data });
_installPlugin(plugin);
}
Comment on lines +137 to +144

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified.deployAndExecuteAndInstallPlugin(address,bytes,IPRBProxyPlugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#137-144): External calls: - proxy = _deploy({owner:msg.sender,target:target,data:data}) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#142) - proxy = new PRBProxy() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#206) - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#143) - methods = plugin.getMethods() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#219) State variables written after the call(s): - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#143) - _methods[owner][plugin] = methods (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#246)
Comment on lines +137 to +144

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified.deployAndExecuteAndInstallPlugin(address,bytes,IPRBProxyPlugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#137-144): External calls: - proxy = _deploy({owner:msg.sender,target:target,data:data}) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#142) - proxy = new PRBProxy() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#206) - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#143) - methods = plugin.getMethods() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#219) Event emitted after the call(s): - InstallPlugin(owner,_proxies[owner],plugin,methods) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#249) - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#143)

/// @inheritdoc IPRBProxyRegistry
function deployAndInstallPlugin(
IPRBProxyPlugin plugin
) external onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
proxy = _deploy({ owner: msg.sender, target: address(0), data: "" });
_installPlugin(plugin);
}
Comment on lines +147 to +152

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified.deployAndInstallPlugin(IPRBProxyPlugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#147-152): External calls: - proxy = _deploy({owner:msg.sender,target:address(0),data:}) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#150) - proxy = new PRBProxy() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#206) - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#151) - methods = plugin.getMethods() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#219) State variables written after the call(s): - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#151) - _methods[owner][plugin] = methods (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#246)
Comment on lines +147 to +152

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified.deployAndInstallPlugin(IPRBProxyPlugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#147-152): External calls: - proxy = _deploy({owner:msg.sender,target:address(0),data:}) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#150) - proxy = new PRBProxy() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#206) - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#151) - methods = plugin.getMethods() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#219) Event emitted after the call(s): - InstallPlugin(owner,_proxies[owner],plugin,methods) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#249) - _installPlugin(plugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#151)

/// @inheritdoc IPRBProxyRegistry
function installPlugin(IPRBProxyPlugin plugin) external override onlyCallerWithProxy {
_installPlugin(plugin);
}

/// @inheritdoc IPRBProxyRegistry
function setPermission(address envoy, address target, bool permission) external override onlyCallerWithProxy {
address owner = msg.sender;
_permissions[owner][envoy][target] = permission;
emit SetPermission(owner, _proxies[owner], envoy, target, permission);
}

/// @inheritdoc IPRBProxyRegistry
function uninstallPlugin(IPRBProxyPlugin plugin) external override onlyCallerWithProxy {
// Retrieve the methods originally installed by this plugin.
address owner = msg.sender;
bytes4[] memory methods = _methods[owner][plugin];

// The plugin must be a known, previously installed plugin.
uint256 length = methods.length;
if (length == 0) {
revert PRBProxyRegistry_PluginUnknown(plugin);
}

// Uninstall every method in the list.
for (uint256 i = 0; i < length; ) {
delete _plugins[owner][methods[i]];
unchecked {
i += 1;
}
}

// Remove the methods from the reverse mapping.
delete _methods[owner][plugin];

// Log the plugin uninstallation.
emit UninstallPlugin(owner, _proxies[owner], plugin, methods);
}

/*//////////////////////////////////////////////////////////////////////////
INTERNAL NON-CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/

/// @dev See the documentation for the user-facing functions that call this internal function.
function _deploy(address owner, address target, bytes memory data) internal returns (IPRBProxy proxy) {
// Use the address of the owner as the CREATE2 salt.
bytes32 salt = bytes32(abi.encodePacked(owner));

// Set the owner and empty out the target and the data to prevent reentrancy.
constructorParams = ConstructorParams({ owner: owner, target: target, data: data });

// Deploy the proxy with CREATE2.
proxy = new PRBProxy{ salt: salt }();
delete constructorParams;

// Associate the owner and the proxy.
_proxies[owner] = proxy;

// Log the creation of the proxy.
emit DeployProxy({ operator: msg.sender, owner: owner, proxy: proxy });
}
Comment on lines +198 to +214

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified._deploy(address,address,bytes) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#198-214): External calls: - proxy = new PRBProxy() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#206) State variables written after the call(s): - _proxies[owner] = proxy (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#210) - delete constructorParams (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#207)
Comment on lines +198 to +214

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified._deploy(address,address,bytes) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#198-214): External calls: - proxy = new PRBProxy() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#206) Event emitted after the call(s): - DeployProxy({operator:msg.sender,owner:owner,proxy:proxy}) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#213)

/// @dev See the documentation for the user-facing functions that call this internal function.
function _installPlugin(IPRBProxyPlugin plugin) internal {
// Retrieve the methods to install.
bytes4[] memory methods = plugin.getMethods();

// The plugin must implement at least one method.
uint256 length = methods.length;
if (length == 0) {
revert PRBProxyRegistry_PluginWithZeroMethods(plugin);
}

// Install every method in the list.
address owner = msg.sender;
for (uint256 i = 0; i < length; ) {
// Check for collisions.
bytes4 method = methods[i];
if (address(_plugins[owner][method]) != address(0)) {
revert PRBProxyRegistry_PluginMethodCollision({
currentPlugin: _plugins[owner][method],
newPlugin: plugin,
method: method
});
}
_plugins[owner][method] = plugin;
unchecked {
i += 1;
}
}

// Set the methods in the reverse mapping.
_methods[owner][plugin] = methods;

// Log the plugin installation.
emit InstallPlugin(owner, _proxies[owner], plugin, methods);
}
Comment on lines +217 to +250

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified._installPlugin(IPRBProxyPlugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#217-250): External calls: - methods = plugin.getMethods() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#219) State variables written after the call(s): - _methods[owner][plugin] = methods (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#246) - _plugins[owner][method] = plugin (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#239)
Comment on lines +217 to +250

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in PRBProxyRegistryModified._installPlugin(IPRBProxyPlugin) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#217-250): External calls: - methods = plugin.getMethods() (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#219) Event emitted after the call(s): - InstallPlugin(owner,_proxies[owner],plugin,methods) (contracts/prebuilts/unaudited/checkout/PRBProxyRegistryModified.sol#249)
}
26 changes: 26 additions & 0 deletions contracts/prebuilts/unaudited/checkout/PluginCheckout.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;

// $$\ $$\ $$\ $$\ $$\
// $$ | $$ | \__| $$ | $$ |
// $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$$$$$$ |$$\ $$\ $$\ $$$$$$\ $$$$$$$\
// \_$$ _| $$ __$$\ $$ |$$ __$$\ $$ __$$ |$$ | $$ | $$ |$$ __$$\ $$ __$$\
// $$ | $$ | $$ |$$ |$$ | \__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ |
// $$ |$$\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ |
// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/

import { IPRBProxyPlugin } from "@prb/proxy/src/interfaces/IPRBProxyPlugin.sol";

import "./TargetCheckout.sol";

contract PluginCheckout is IPRBProxyPlugin, TargetCheckout {
function getMethods() external pure override returns (bytes4[] memory) {
bytes4[] memory methods = new bytes4[](4);
methods[0] = this.withdraw.selector;
methods[1] = this.execute.selector;
methods[2] = this.swapAndExecute.selector;
methods[3] = this.approveSwapRouter.selector;
return methods;
}
}
82 changes: 82 additions & 0 deletions contracts/prebuilts/unaudited/checkout/TargetCheckout.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;

import "../../../lib/CurrencyTransferLib.sol";
import "../../../eip/interface/IERC20.sol";

import { IPRBProxy } from "@prb/proxy/src/interfaces/IPRBProxy.sol";
import "./interface/IPluginCheckout.sol";

// $$\ $$\ $$\ $$\ $$\
// $$ | $$ | \__| $$ | $$ |
// $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$$$$$$ |$$\ $$\ $$\ $$$$$$\ $$$$$$$\
// \_$$ _| $$ __$$\ $$ |$$ __$$\ $$ __$$ |$$ | $$ | $$ |$$ __$$\ $$ __$$\
// $$ | $$ | $$ |$$ |$$ | \__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ |
// $$ |$$\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ |
// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/

contract TargetCheckout is IPluginCheckout {
mapping(address => bool) public isApprovedRouter;

function withdraw(address _token, uint256 _amount) external {
require(msg.sender == IPRBProxy(address(this)).owner(), "Not authorized");

CurrencyTransferLib.transferCurrency(_token, address(this), msg.sender, _amount);
}

function approveSwapRouter(address _swapRouter, bool _toApprove) external {
require(msg.sender == IPRBProxy(address(this)).owner(), "Not authorized");
require(_swapRouter != address(0), "Zero address");

isApprovedRouter[_swapRouter] = _toApprove;
}

function execute(UserOp memory op) external {
require(_canExecute(op, msg.sender), "Not authorized");

_execute(op);
}

function swapAndExecute(UserOp memory op, UserOp memory swapOp) external {
require(isApprovedRouter[swapOp.target], "Invalid router address");
require(_canExecute(op, msg.sender), "Not authorized");

_execute(swapOp);
_execute(op);
}

// =================================================
// =============== Internal functions ==============
// =================================================

function _execute(UserOp memory op) internal {
bool success;
if (op.currency == CurrencyTransferLib.NATIVE_TOKEN) {
(success, ) = op.target.call{ value: op.valueToSend }(op.data);
} else {
if (op.valueToSend != 0 && op.approvalRequired) {
IERC20(op.currency).approve(op.target, op.valueToSend);
}

(success, ) = op.target.call(op.data);
}

require(success, "Execution failed");
}

Check failure

Code scanning / Slither

Functions that send Ether to arbitrary destinations

TargetCheckout._execute(IPluginCheckout.UserOp) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#53-66) sends eth to arbitrary user Dangerous calls: - (success,None) = op.target.call{value: op.valueToSend}(op.data) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#56)

Check warning

Code scanning / Slither

Unused return

TargetCheckout._execute(IPluginCheckout.UserOp) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#53-66) ignores return value by IERC20(op.currency).approve(op.target,op.valueToSend) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#59)

Check warning

Code scanning / Slither

Low-level calls

Low level call in TargetCheckout._execute(IPluginCheckout.UserOp) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#53-66): - (success,None) = op.target.call{value: op.valueToSend}(op.data) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#56) - (success,None) = op.target.call(op.data) (contracts/prebuilts/unaudited/checkout/TargetCheckout.sol#62)

function _canExecute(UserOp memory op, address caller) internal view returns (bool) {
address owner = IPRBProxy(address(this)).owner();
if (owner != caller) {
bool permission = IPRBProxy(address(this)).registry().getPermissionByOwner({
owner: owner,
envoy: caller,
target: op.target
});

return permission;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;

interface IPluginCheckout {
/**
* @notice Details of the transaction to execute on target contract.
*
* @param target Address to send the transaction to
*
* @param currency Represents both native token and erc20 token
*
* @param approvalRequired If need to approve erc20 to the target contract
*
* @param valueToSend Transaction value to send - both native and erc20
*
* @param data Transaction calldata
*/
struct UserOp {
address target;
address currency;
bool approvalRequired;
uint256 valueToSend;
bytes data;
}

function execute(UserOp calldata op) external;

function swapAndExecute(UserOp calldata op, UserOp memory swapOp) external;
}
Loading