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

Woz/frontend update #53

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
44 changes: 44 additions & 0 deletions contracts/IOjo.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ interface IOjo {
bytes calldata commandParams
) external payable;

/// @notice Triggers the relaying of price data from the Ojo Network to the Ojo contract and uses said price data
/// when calling the specified contract method at the specified contract address. Uses ERC-20 token for gas payment
/// instead of native gas.
/// @dev Reverts if contract method call does not succeed.
/// @param assetNames List of assets to be relayed from the Ojo Network and used by the contract method.
/// @param contractAddress Address of contract containing the contract method to be called.
/// @param commandSelector First four bytes of the Keccak-256 hash of the contract method to be called.
/// @param commandParams Abi encoded parameters to be used when calling the contract method (excluding assetNames
/// parameter).
/// @param gasToken The address of the ERC-20 token used to pay for gas.
/// @param gasFeeAmount The amount of tokens to pay for gas.
function callContractMethodWithOjoPriceDataNonNativeGas(
bytes32[] calldata assetNames,
address contractAddress,
bytes4 commandSelector,
bytes calldata commandParams,
address gasToken,
uint256 gasFeeAmount
) external;

/// @notice Triggers the relaying of price data from the Ojo Network to the Ojo contract with an ERC-20 token for
/// and uses said price data when calling the specified contract method at the specified contract address.
/// @dev Reverts if contract method call does not succeed.
Expand All @@ -48,6 +68,30 @@ interface IOjo {
uint256 amount
) external payable;

/// @notice Triggers the relaying of price data from the Ojo Network to the Ojo contract with an ERC-20 token for
/// and uses said price data when calling the specified contract method at the specified contract address. Uses
/// ERC-20 token for gas payment instead of native gas.
/// @dev Reverts if contract method call does not succeed.
/// @param assetNames List of assets to be relayed from the Ojo Network and used by the contract method.
/// @param contractAddress Address of contract containing the contract method to be called.
/// @param commandSelector First four bytes of the Keccak-256 hash of the contract method to be called.
/// @param commandParams Abi encoded parameters to be used when calling the contract method (excluding assetNames
/// parameter).
/// @param symbol The symbol of the token to be sent with the call.
/// @param amount The amount of tokens to be sent with the call.
/// @param gasToken The address of the ERC-20 token used to pay for gas.
/// @param gasFeeAmount The amount of tokens to pay for gas.
function callContractMethodWithOjoPriceDataAndTokenNonNativeGas(
bytes32[] calldata assetNames,
address contractAddress,
bytes4 commandSelector,
bytes calldata commandParams,
string memory symbol,
uint256 amount,
address gasToken,
uint256 gasFeeAmount
) external;

/// @notice Returns the price data of a specified asset.
/// @dev Price data is stored in a mapping, so requesting the price data of a non existent asset will return the
/// zero byte representation of OjoTypes.PriceData.
Expand Down
48 changes: 48 additions & 0 deletions contracts/MockOjo.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ contract MockOjo {
);
}

function relayOjoPriceDataNonNativeGas(
bytes32[] calldata assetNames,
address gasToken,
uint256 gasFeeAmount
) external payable {
IERC20(gasToken).transferFrom(msg.sender, address(this), gasFeeAmount);
IERC20(gasToken).approve(address(ojo), gasFeeAmount);

bytes memory commandParams = "0x";

ojo.callContractMethodWithOjoPriceDataNonNativeGas(
assetNames,
address(this),
OjoTypes.EMPTY_COMMAND_SELECTOR,
commandParams,
gasToken,
gasFeeAmount
);
}

function relayOjoPriceDataWithToken(
bytes32[] calldata assetNames,
string memory symbol,
Expand All @@ -56,6 +76,34 @@ contract MockOjo {
);
}

function relayOjoPriceDataWithTokenNonNativeGas(
bytes32[] calldata assetNames,
string memory symbol,
uint256 amount,
address tokenAddress,
address gasToken,
uint256 gasFeeAmount
) external payable {
IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);
IERC20(tokenAddress).approve(address(ojo), amount);

IERC20(gasToken).transferFrom(msg.sender, address(this), gasFeeAmount);
IERC20(gasToken).approve(address(ojo), gasFeeAmount);

bytes memory commandParams = "0x";

ojo.callContractMethodWithOjoPriceDataAndTokenNonNativeGas(
assetNames,
address(this),
OjoTypes.EMPTY_COMMAND_SELECTOR,
commandParams,
symbol,
amount,
gasToken,
gasFeeAmount
);
}

function setBalanceWithOjoPriceData(
bytes32[] calldata assetNames,
uint256 multiplier
Expand Down
70 changes: 70 additions & 0 deletions contracts/Ojo.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,37 @@ contract Ojo is IOjo, AxelarExpressExecutable, Upgradable {
gateway.callContract(ojoChain, ojoAddress, payloadWithVersion);
}

function callContractMethodWithOjoPriceDataNonNativeGas(
bytes32[] calldata assetNames,
address contractAddress,
bytes4 commandSelector,
bytes calldata commandParams,
address gasToken,
uint256 gasFeeAmount
) external {
require(assetNames.length <= assetLimit, "Number of assets requested is over limit");

bytes memory payloadWithVersion = abi.encodePacked(
bytes4(uint32(0)), // version number
abi.encode(assetNames, contractAddress, commandSelector, commandParams, block.timestamp) // payload
);

IERC20(gasToken).transferFrom(msg.sender, address(this), gasFeeAmount);
IERC20(gasToken).approve(address(gasReceiver), gasFeeAmount);

gasReceiver.payGasForContractCall(
address(this),
ojoChain,
ojoAddress,
payloadWithVersion,
gasToken,
gasFeeAmount,
msg.sender
);

gateway.callContract(ojoChain, ojoAddress, payloadWithVersion);
}

function callContractMethodWithOjoPriceDataAndToken(
bytes32[] calldata assetNames,
address contractAddress,
Expand Down Expand Up @@ -84,6 +115,45 @@ contract Ojo is IOjo, AxelarExpressExecutable, Upgradable {
gateway.callContractWithToken(ojoChain, ojoAddress, payloadWithVersion, symbol, amount);
}

function callContractMethodWithOjoPriceDataAndTokenNonNativeGas(
bytes32[] calldata assetNames,
address contractAddress,
bytes4 commandSelector,
bytes calldata commandParams,
string memory symbol,
uint256 amount,
address gasToken,
uint256 gasFeeAmount
) external {
require(assetNames.length <= assetLimit, "Number of assets requested is over limit");

address tokenAddress = gateway.tokenAddresses(symbol);
IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);
IERC20(tokenAddress).approve(address(gateway), amount);

IERC20(gasToken).transferFrom(msg.sender, address(this), gasFeeAmount);
IERC20(gasToken).approve(address(gasReceiver), gasFeeAmount);

bytes memory payloadWithVersion = abi.encodePacked(
bytes4(uint32(0)), // version number
abi.encode(assetNames, contractAddress, commandSelector, commandParams, block.timestamp) // payload
);

gasReceiver.payGasForContractCallWithToken(
address(this),
ojoChain,
ojoAddress,
payloadWithVersion,
symbol,
amount,
gasToken,
gasFeeAmount,
msg.sender
);

gateway.callContractWithToken(ojoChain, ojoAddress, payloadWithVersion, symbol, amount);
}

function _setup(bytes calldata data) internal override {
(string memory ojoChain_, string memory ojoAddress_, uint256 resolveWindow_, uint16 assetLimit_) = abi.decode(
data,
Expand Down
Loading
Loading