Skip to content

Commit

Permalink
Merge pull request #9 from VenusProtocol/feat/VEN-2243
Browse files Browse the repository at this point in the history
[VEN-2243]: override sendAndCall function and introduce sendAndCallEnabled  with its setter
  • Loading branch information
GitGuru7 authored Dec 20, 2023
2 parents ef5cfa7 + c017c2c commit a1e8cd5
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 17 deletions.
73 changes: 56 additions & 17 deletions contracts/Bridge/BaseXVSProxyOFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
using SafeERC20 for IERC20;
IERC20 internal immutable innerToken;

Check warning on line 24 in contracts/Bridge/BaseXVSProxyOFT.sol

View workflow job for this annotation

GitHub Actions / Lint

Immutable variables name are set to be in capitalized SNAKE_CASE
uint256 internal immutable ld2sdRate;

Check warning on line 25 in contracts/Bridge/BaseXVSProxyOFT.sol

View workflow job for this annotation

GitHub Actions / Lint

Immutable variables name are set to be in capitalized SNAKE_CASE
bool public sendAndCallEnabled;

/**
* @notice The address of ResilientOracle contract wrapped in its interface.
Expand Down Expand Up @@ -97,12 +98,14 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
* @notice Event emitted when inner token set successfully.
*/
event InnerTokenAdded(address indexed innerToken);

/**
*@notice Emitted on sweep token success
*/
event SweepToken(address indexed token, address indexed to, uint256 sweepAmount);

/**
* @notice Event emitted when SendAndCallEnabled updated successfully.
*/
event UpdateSendAndCallEnabled(bool indexed enabled);
/**
*@notice Error thrown when this contract balance is less than sweep amount
*/
Expand Down Expand Up @@ -271,21 +274,13 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
emit TrustedRemoteRemoved(remoteChainId_);
}

function retryMessage(
uint16 _srcChainId,
bytes calldata _srcAddress,
uint64 _nonce,
bytes calldata _payload
) public payable override {
bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];
// it will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.
require(
_srcAddress.length == trustedRemote.length &&
trustedRemote.length > 0 &&
keccak256(_srcAddress) == keccak256(trustedRemote),
"LzApp: invalid source sending contract"
);
super.retryMessage(_srcChainId, _srcAddress, _nonce, _payload);
/**
* @notice It enables or disables sendAndCall functionality for the bridge.
* @param enabled_ Boolean indicating whether the sendAndCall function should be enabled or disabled.
*/
function updateSendAndCallEnabled(bool enabled_) external onlyOwner {
sendAndCallEnabled = enabled_;
emit UpdateSendAndCallEnabled(enabled_);
}

/**
Expand Down Expand Up @@ -343,6 +338,50 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
((amountInUsd <= maxSingleTransactionLimit) && (transferredInWindow <= maxDailyLimit)));
}

/**
* @notice Initiates a cross-chain token transfer and triggers a call on the destination chain.
* @dev This internal override function enables the contract to send tokens and invoke calls on the specified
* destination chain. It checks whether the sendAndCall feature is enabled before proceeding with the transfer.
* @param from_ Address from which tokens will be debited.
* @param dstChainId_ Destination chain id on which tokens will be send.
* @param toAddress_ Address on which tokens will be credited on destination chain.
* @param amount_ Amount of tokens that will be transferred.
* @param payload_ Additional data payload for the call on the destination chain.
* @param dstGasForCall_ The amount of gas allocated for the call on the destination chain.
* @param callparams_ Additional parameters, including refund address, ZRO payment address,
* and adapter params.
*/
function sendAndCall(
address from_,
uint16 dstChainId_,
bytes32 toAddress_,
uint256 amount_,
bytes calldata payload_,
uint64 dstGasForCall_,
LzCallParams calldata callparams_
) public payable override {
require(sendAndCallEnabled, "sendAndCall is disabled");

Check warning on line 363 in contracts/Bridge/BaseXVSProxyOFT.sol

View workflow job for this annotation

GitHub Actions / Lint

Use Custom Errors instead of require statements

super.sendAndCall(from_, dstChainId_, toAddress_, amount_, payload_, dstGasForCall_, callparams_);
}

function retryMessage(
uint16 _srcChainId,
bytes calldata _srcAddress,
uint64 _nonce,
bytes calldata _payload
) public payable override {
bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];
// it will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.
require(

Check warning on line 376 in contracts/Bridge/BaseXVSProxyOFT.sol

View workflow job for this annotation

GitHub Actions / Lint

Use Custom Errors instead of require statements
_srcAddress.length == trustedRemote.length &&
trustedRemote.length > 0 &&
keccak256(_srcAddress) == keccak256(trustedRemote),
"LzApp: invalid source sending contract"
);
super.retryMessage(_srcChainId, _srcAddress, _nonce, _payload);
}

/**
* @notice Empty implementation of renounce ownership to avoid any mishappening.
*/
Expand Down
1 change: 1 addition & 0 deletions helpers/deploymentConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const xvsBridgeMethods = [
"setWhitelist(address,bool)",
"setConfig(uint16,uint16,uint256,bytes)",
"sweepToken(address,address,uint256)",
"updateSendAndCallEnabled(bool)",
];

export const bridgeAdminMethods = ["setTrustedRemoteAddress(uint16,bytes)", "transferBridgeOwnership(address)"];
Expand Down
62 changes: 62 additions & 0 deletions test/proxyOFT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ describe("Proxy OFTV2: ", function () {
"setPayloadSizeLimit(uint16,uint256)",
"setUseCustomAdapterParams(bool)",
"removeTrustedRemote(uint16)",
"updateSendAndCallEnabled(bool)",
];
const activeArray = new Array(functionregistry.length).fill(true);
await bridgeAdminRemote.upsertSignature(functionregistry, activeArray);
Expand Down Expand Up @@ -854,4 +855,65 @@ describe("Proxy OFTV2: ", function () {
expect(await localOFT.chainIdToLast24HourWindowStart(remoteChainId)).to.be.equals(last24HourWindowStart);
expect(await localOFT.whitelist(acc2.address)).to.be.equals(isWhiteListedUser);
});
it("Reverts when sendAndCall is disabled", async function () {
const amount = ethers.utils.parseEther("2", 18);
const dstGasForCall_ = 0;
const uint160Value = BigInt("0x" + acc3.address.slice(2));
const bytes32Value = uint160Value << BigInt(96);
const acc3AddressBytes32 = "0x" + bytes32Value.toString(16).padStart(32, "0");

await expect(
localOFT
.connect(acc1)
.sendAndCall(acc3.address, remoteChainId, acc3AddressBytes32, amount, "0x", dstGasForCall_, [
acc1.address,
acc1.address,
"0x",
]),
).to.be.revertedWith("sendAndCall is disabled");
});

it("Successfully call sendAndCall", async function () {
const uint160Value = BigInt("0x" + acc3.address.slice(2));
const bytes32Value = uint160Value << BigInt(96);
const acc3AddressBytes32 = "0x" + bytes32Value.toString(16).padStart(32, "0");
let data = localOFT.interface.encodeFunctionData("setMinDstGas", [remoteChainId, 1, 300000]);
const amount = ethers.utils.parseEther("2", 18);
const dstGasForCall_ = 0;
await acc1.sendTransaction({
to: bridgeAdminLocal.address,
data: data,
});

await acc1.sendTransaction({
to: bridgeAdminLocal.address,
data: data,
});
data = localOFT.interface.encodeFunctionData("updateSendAndCallEnabled", [true]);
await acc1.sendTransaction({
to: bridgeAdminLocal.address,
data: data,
});

const adapterParams = ethers.utils.solidityPack(["uint16", "uint256"], [1, 300000]);
await localToken.connect(acc1).faucet(amount);
await localToken.connect(acc1).approve(localOFT.address, amount);
expect(await localOFT.sendAndCallEnabled()).to.be.true;

const nativeFee = (await localOFT.estimateSendFee(remoteChainId, acc3AddressBytes32, amount, false, adapterParams))
.nativeFee;

await localOFT
.connect(acc1)
.sendAndCall(
acc1.address,
remoteChainId,
acc3AddressBytes32,
amount,
"0x",
dstGasForCall_,
[acc1.address, acc1.address, adapterParams],
{ value: nativeFee },
);
});
});

0 comments on commit a1e8cd5

Please sign in to comment.