Skip to content

Commit

Permalink
TransferFunds script enables sending of varying amounts of LSK tokens…
Browse files Browse the repository at this point in the history
… to different addresses
  • Loading branch information
matjazv committed Jan 2, 2024
1 parent 84764c8 commit 704ddd3
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 18 deletions.
98 changes: 81 additions & 17 deletions script/TransferFunds.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ interface IL1StandardBridge {
}

/// @title TransferFundsScript - L1 Lisk token transfer script
/// @notice This contract is used to transfer all deployer's L1 Lisk tokens to the L2 Claim contract via L1 Standard
/// Bridge.
/// @notice This contract is used to transfer all deployer's L1 Lisk tokens to a different addresses on L1 and L2
/// networks. When sending tokens to the L2 network, the L1 Standard Bridge contract is used.
contract TransferFundsScript is Script {
/// @notice Utils contract which provides functions to read and write JSON files containing L1 and L2 addresses.
Utils utils;
Expand All @@ -39,15 +39,16 @@ contract TransferFundsScript is Script {
utils = new Utils();
}

/// @notice This function transfers L1 Lisk tokens to the L2 Claim contract.
/// @dev This function first approves L1 Standard Bridge to transfer all deployer's L1 Lisk tokens and then calls
/// the depositERC20To function of the L1 Standard Bridge contract to transfer all deployer's L1 Lisk tokens to the
/// L2 Claim contract.
/// @notice This function transfers L1 Lisk tokens to a different addresses on L1 and L2 networks.
/// @dev This function first sends deployer's L1 Lisk tokens to all L1 addresses specified in the accounts.json
/// file. After it approves L1 Standard Bridge to transfer all remaining deployer's L1 Lisk tokens to the L2
/// network. It does this in two steps. First it sends tokens to all L2 addresses specified in the
/// accounts.json file. After it transfers all remaining tokens to the L2 Claim contract.
function run() public {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address l1StandardBridge = vm.envAddress("L1_STANDARD_BRIDGE_ADDR");

console2.log("Simulation: Transferring Lisk tokens from L1 to L2 Claim contract...");
console2.log("Simulation: Transferring Lisk tokens from L1 to a different addresses on L1 and L2 networks...");

// get L1LiskToken contract address
Utils.L1AddressesConfig memory l1AddressesConfig = utils.readL1AddressesFile();
Expand All @@ -58,37 +59,100 @@ contract TransferFundsScript is Script {
console2.log("Simulation: L2 Lisk token address: %s", l2AddressesConfig.L2LiskToken);
console2.log("Simulation: L2 Claim contract address: %s", l2AddressesConfig.L2ClaimContract);

// get accounts to which L1 Lisk tokens will be transferred
Utils.Accounts memory accounts = utils.readAccountsFile();
console2.log("Simulation: Number of L1 addresses: %s", accounts.l1Addresses.length);
for (uint256 i = 0; i < accounts.l1Addresses.length; i++) {
console2.log("Simulation: %d: %s", i + 1, accounts.l1Addresses[i].addr);
}
console2.log("Simulation: Number of L2 addresses: %s", accounts.l2Addresses.length);
for (uint256 i = 0; i < accounts.l2Addresses.length; i++) {
console2.log("Simulation: %d: %s", i + 1, accounts.l2Addresses[i].addr);
}

// get L1LiskToken and L1StandardBridge contracts instances
L1LiskToken l1LiskToken = L1LiskToken(address(l1AddressesConfig.L1LiskToken));
IL1StandardBridge bridge = IL1StandardBridge(l1StandardBridge);

console2.log("Simulation: Sending L1 Lisk tokens to all L1 addresses...");

// send L1 Lisk tokens to all L1 addresses
for (uint256 i = 0; i < accounts.l1Addresses.length; i++) {
console2.log(
"Simulation: Sending %s L1 Lisk tokens to L1 address: %s",
accounts.l1Addresses[i].amount,
accounts.l1Addresses[i].addr
);
vm.startBroadcast(deployerPrivateKey);
l1LiskToken.transfer(accounts.l1Addresses[i].addr, accounts.l1Addresses[i].amount);
vm.stopBroadcast();
}

for (uint256 i = 0; i < accounts.l1Addresses.length; i++) {
assert(l1LiskToken.balanceOf(accounts.l1Addresses[i].addr) == accounts.l1Addresses[i].amount);
}

console2.log("Simulation: L1 Lisk tokens successfully sent to all L1 addresses!");

// balance of L1 Lisk tokens before sending them to L2 addresses
uint256 balanceBefore = l1LiskToken.balanceOf(vm.addr(deployerPrivateKey));

console2.log(
"Simulation: Approving L1 Lisk tokens to be transfered by L1 Standard Bridge to the L2 Lisk token contract: %s",
l1LiskToken.balanceOf(vm.addr(deployerPrivateKey))
"Simulation: Approving all remaining L1 Lisk tokens to be transfered by L1 Standard Bridge to the L2 network: %s",
balanceBefore
);
vm.startBroadcast(deployerPrivateKey);
l1LiskToken.approve(address(bridge), l1LiskToken.balanceOf(vm.addr(deployerPrivateKey)));
l1LiskToken.approve(address(bridge), balanceBefore);
vm.stopBroadcast();

assert(
l1LiskToken.allowance(vm.addr(deployerPrivateKey), address(bridge))
== l1LiskToken.balanceOf(vm.addr(deployerPrivateKey))
);
assert(l1LiskToken.allowance(vm.addr(deployerPrivateKey), address(bridge)) == balanceBefore);

console2.log("Simulation: L1 Lisk tokens successfully approved to be transfered by L1 Standard Bridge!");

console2.log("Simulation: Sending L1 Lisk tokens to all L2 addresses...");

// send L1 Lisk tokens to all L2 addresses
for (uint256 i = 0; i < accounts.l2Addresses.length; i++) {
console2.log(
"Simulation: Sending %s L1 Lisk tokens to L2 address: %s",
accounts.l2Addresses[i].amount,
accounts.l2Addresses[i].addr
);
vm.startBroadcast(deployerPrivateKey);
bridge.depositERC20To(
l1AddressesConfig.L1LiskToken,
l2AddressesConfig.L2LiskToken,
accounts.l2Addresses[i].addr,
accounts.l2Addresses[i].amount,
1000000,
""
);
vm.stopBroadcast();
}

// total amount of tokens sent to L2 addresses
uint256 totalAmount = 0;
for (uint256 i = 0; i < accounts.l2Addresses.length; i++) {
totalAmount += accounts.l2Addresses[i].amount;
}
assert(l1LiskToken.balanceOf(vm.addr(deployerPrivateKey)) == balanceBefore - totalAmount);

console2.log("Simulation: L1 Lisk tokens successfully sent to all L2 addresses!");

console2.log("Simulation: Transferring all L1 Lisk tokens to the L2 Claim contract...");
console2.log("Simulation: Transferring all remaining L1 Lisk tokens to the L2 Claim contract...");
vm.startBroadcast(deployerPrivateKey);
bridge.depositERC20To(
l1AddressesConfig.L1LiskToken,
l2AddressesConfig.L2LiskToken,
l2AddressesConfig.L2ClaimContract,
l1LiskToken.balanceOf(vm.addr(deployerPrivateKey)),
balanceBefore - totalAmount,
1000000,
""
);
vm.stopBroadcast();

assert(l1LiskToken.balanceOf(vm.addr(deployerPrivateKey)) == 0);
assert(l1LiskToken.balanceOf(l1StandardBridge) == 200000000 * 10 ** 18);
assert(l1LiskToken.balanceOf(l1StandardBridge) == balanceBefore);

console2.log("Simulation: L1 Lisk tokens successfully transferred to the L2 Claim contract!");
}
Expand Down
27 changes: 27 additions & 0 deletions script/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@ contract Utils is Script {
address L2LiskToken;
}

/// @notice This struct is used to read accounts from JSON file. These accounts are used to transfer L1 Lisk tokens
/// to them after all contracts are deployed.
struct Accounts {
/// @notice Array of L1 addresses and amounts of LSK tokens to be transferred to them.
FundedAccount[] l1Addresses;
/// @notice Array of L2 addresses and amounts of LSK tokens to be transferred to them.
FundedAccount[] l2Addresses;
}

/// @notice This struct is used to read a single account from JSON file.
struct FundedAccount {
/// @notice Account address.
address addr;
/// @notice Amount of LSK tokens to be transferred to the account.
uint256 amount;
}

/// @notice This function reads L1 addresses from JSON file.
/// @return L1AddressesConfig struct containing L1 addresses.
function readL1AddressesFile() external view returns (L1AddressesConfig memory) {
Expand Down Expand Up @@ -59,4 +76,14 @@ contract Utils is Script {
string memory finalJson = vm.serializeAddress(json, "L2LiskToken", cfg.L2LiskToken);
finalJson.write(string.concat("deployment/l2addresses.json"));
}

/// @notice This function reads accounts from JSON file.
/// @return Accounts struct containing accounts.
function readAccountsFile() external view returns (Accounts memory) {
string memory root = vm.projectRoot();
string memory accountsPath = string.concat(root, "/script/data/devnet/accounts.json");
string memory accountsJson = vm.readFile(accountsPath);
bytes memory accountsRaw = vm.parseJson(accountsJson);
return abi.decode(accountsRaw, (Accounts));
}
}
22 changes: 22 additions & 0 deletions script/data/devnet/accounts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"l1Addresses": [
{
"addr": "0xe708A1b91dDC44576731f7fEb4e193F48923Abba",
"amount": 2000000000000000000000
},
{
"addr": "0x1CA256b7a7883FFb046F39fC0602311B88C04AF9",
"amount": 4000000000000000000000
}
],
"l2Addresses": [
{
"addr": "0x396df972a284ba7f5a8bec2d9b9ec2377a099215",
"amount": 3000000000000000000000
},
{
"addr": "0xf50c46F0b23a0e90409E7270568Dbb62522c28B9",
"amount": 5000000000000000000000
}
]
}
2 changes: 1 addition & 1 deletion script/deployContracts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ forge script --rpc-url="$L2_RPC_URL" --broadcast --verify --etherscan-api-key="$
fi
echo "Done."

echo "Transferring funds to L2Claim smart contract..."
echo "Transferring funds to L1 and L2 addresses and L2Claim smart contract..."
forge script --rpc-url="$L1_RPC_URL" --broadcast -vvvv script/TransferFunds.s.sol:TransferFundsScript
echo "Done."

0 comments on commit 704ddd3

Please sign in to comment.