Skip to content

Commit

Permalink
refactor: comments and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
GitGuru7 committed Dec 14, 2023
1 parent acc9dfb commit 0060366
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 20 deletions.
55 changes: 35 additions & 20 deletions contracts/Bridge/BaseXVSProxyOFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,19 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
}

/**
* @notice View function similar to _isEligibleToSend internal function.
* @param from_ Address on which eligibility has to be checked.
* @param dstChainId_ Destination chain id.
* @param amount_ Amount of tokens.
* @return isEligibleToSend_ boolean indicating eligibility to send tokens.
* @return maxSingleTransactionLimit Maximum single transaction limit corresponding to chain id.
* @return maxDailyLimit Maximum daily limit to send tokens.
* @return amountInUsd Amount in USD.
* @return transferredInWindow Number of tokens transferred in 24 hour window.
* @return last24HourWindowStart Timestamp marking the start of the last 24-hour window.
* @return isWhiteListedUser Boolean indicating whether the sender is whitelisted.
* @notice Checks the eligibility of a sender to initiate a cross-chain token transfer.
* @dev This external view function assesses whether the specified sender is eligible to transfer the given amount
* to the specified destination chain. It considers factors such as whitelisting, transaction limits, and a 24-hour window.
* @param from_ The sender's address initiating the transfer.
* @param dstChainId_ Indicates destination chain.
* @param amount_ The quantity of tokens to be transferred.
* @return eligibleToSend A boolean indicating whether the sender is eligible to transfer the tokens.
* @return maxSingleTransactionLimit The maximum limit for a single transaction.
* @return maxDailyLimit The maximum daily limit for transactions.
* @return amountInUsd The equivalent amount in USD based on the oracle price.
* @return transferredInWindow The total amount transferred in the current 24-hour window.
* @return last24HourWindowStart The timestamp when the current 24-hour window started.
* @return isWhiteListedUser A boolean indicating whether the sender is whitelisted.
*/
function isEligibleToSend(
address from_,
Expand All @@ -259,7 +261,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
external
view
returns (
bool isEligibleToSend_,
bool eligibleToSend,
uint256 maxSingleTransactionLimit,
uint256 maxDailyLimit,
uint256 amountInUsd,
Expand All @@ -276,20 +278,33 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 {
amountInUsd = mul_ScalarTruncate(oraclePrice, amount_);

// Load values for the 24-hour window checks
uint256 currentBlockTimestamp = block.timestamp;
last24HourWindowStart = chainIdToLast24HourWindowStart[dstChainId_];
transferredInWindow = chainIdToLast24HourTransferred[dstChainId_];
maxSingleTransactionLimit = chainIdToMaxSingleTransactionLimit[dstChainId_];
maxDailyLimit = chainIdToMaxDailyLimit[dstChainId_];

// Check if the time window has changed (more than 24 hours have passed)
if (block.timestamp - last24HourWindowStart > 1 days) {
transferredInWindow = amountInUsd;
if (!isWhiteListedUser) {
// Check if the time window has changed (more than 24 hours have passed)
if (currentBlockTimestamp - last24HourWindowStart > 1 days) {
transferredInWindow = amountInUsd;
last24HourWindowStart = currentBlockTimestamp;
} else {
transferredInWindow += amountInUsd;
}
eligibleToSend = (whitelist[from_] ||
((amountInUsd <= maxSingleTransactionLimit) &&
(transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_])));
} else {
transferredInWindow += amountInUsd;
return (
true,
maxSingleTransactionLimit,
maxDailyLimit,
amountInUsd,
transferredInWindow,
last24HourWindowStart,
isWhiteListedUser
);
}
isEligibleToSend_ = (whitelist[from_] ||
((amountInUsd <= maxSingleTransactionLimit) &&
(transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_])));
}

/**
Expand Down
84 changes: 84 additions & 0 deletions test/proxyOFT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -718,4 +718,88 @@ describe("Proxy OFTV2: ", function () {
});
expect(await localOFT.trustedRemoteLookup(remoteChainId)).equals("0x");
});
it("Returns correct limits and eligibility of user initially", async function () {
const amount = ethers.utils.parseEther("10", 18);
const {
eligibleToSend,
maxSingleTransactionLimit,
maxDailyLimit,
amountInUsd,
transferredInWindow,
last24HourWindowStart,
isWhiteListedUser,
} = await localOFT.connect(acc1).isEligibleToSend(acc2.address, remoteChainId, amount);
expect(eligibleToSend).to.be.true;
expect(await localOFT.chainIdToMaxSingleTransactionLimit(remoteChainId)).to.be.equals(maxSingleTransactionLimit);
expect(await localOFT.chainIdToMaxDailyLimit(remoteChainId)).to.be.equals(maxDailyLimit);
const oraclePrice = await oracle.getPrice(await localOFT.token());
const expectedAmount = BigInt((oraclePrice * amount) / 1e18);
expect(expectedAmount).to.be.equals(amountInUsd);
expect((await localOFT.chainIdToLast24HourTransferred(remoteChainId)).add(amountInUsd)).to.be.equals(
transferredInWindow,
);
const currentTimestamp = (await ethers.provider.getBlock("latest")).timestamp;
expect((await localOFT.chainIdToLast24HourWindowStart(remoteChainId)).add(currentTimestamp)).to.be.equals(
last24HourWindowStart,
);
expect(await localOFT.whitelist(acc2.address)).to.be.equals(isWhiteListedUser);
});

it("Returns upadted value of limits and eligibility of user", async function () {
const data = localOFT.interface.encodeFunctionData("setMaxSingleTransactionLimit", [
remoteChainId,
singleTransactionLimit,
]);
await acc1.sendTransaction({
to: bridgeAdminLocal.address,
data: data,
});

const initialAmount = ethers.utils.parseEther("1", 18);
await localToken.connect(acc2).faucet(initialAmount);
// verify acc2 has tokens and acc3 has no tokens on remote chain
expect(await localToken.balanceOf(acc2.address)).to.be.equal(initialAmount);
expect(await remoteToken.balanceOf(acc3.address)).to.be.equal(0);
// acc2 sends tokens to acc3 on remote chain
// approve the proxy to swap your tokens
await localToken.connect(acc2).approve(localOFT.address, initialAmount);
// swaps token to remote chain
const acc3AddressBytes32 = ethers.utils.defaultAbiCoder.encode(["address"], [acc3.address]);
const nativeFee = (
await localOFT.estimateSendFee(remoteChainId, acc3AddressBytes32, initialAmount, false, defaultAdapterParams)
).nativeFee;

await localOFT
.connect(acc2)
.sendFrom(
acc2.address,
remoteChainId,
acc3AddressBytes32,
initialAmount,
[acc2.address, ethers.constants.AddressZero, defaultAdapterParams],
{ value: nativeFee },
);

const {
eligibleToSend,
maxSingleTransactionLimit,
maxDailyLimit,
amountInUsd,
transferredInWindow,
last24HourWindowStart,
isWhiteListedUser,
} = await localOFT.connect(acc1).isEligibleToSend(acc2.address, remoteChainId, initialAmount);

expect(eligibleToSend).to.be.true;
expect(await localOFT.chainIdToMaxSingleTransactionLimit(remoteChainId)).to.be.equals(maxSingleTransactionLimit);
expect(await localOFT.chainIdToMaxDailyLimit(remoteChainId)).to.be.equals(maxDailyLimit);
const oraclePrice = await oracle.getPrice(await localOFT.token());
const expectedAmount = BigInt((oraclePrice * initialAmount) / 1e18);
expect(expectedAmount).to.be.equals(amountInUsd);
expect((await localOFT.chainIdToLast24HourTransferred(remoteChainId)).add(amountInUsd)).to.be.equals(
transferredInWindow,
);
expect(await localOFT.chainIdToLast24HourWindowStart(remoteChainId)).to.be.equals(last24HourWindowStart);
expect(await localOFT.whitelist(acc2.address)).to.be.equals(isWhiteListedUser);
});
});

0 comments on commit 0060366

Please sign in to comment.