Skip to content

Commit 1abe4c6

Browse files
Scaffold project from send-token-upgrade
Why: Bootstrap repository structure using the known baseline to accelerate initial setup while keeping consistent tooling. Test plan: - List files; key scaffolding files exist. - bunx hardhat compile succeeds.
1 parent 66c2523 commit 1abe4c6

File tree

15 files changed

+409
-0
lines changed

15 files changed

+409
-0
lines changed

.env.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
EOA_DEPLOYER=...
2+
ETHERSCAN_API_KEY=...

.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dotenv_if_exists .env

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Compiler files
2+
cache/
3+
out/
4+
5+
# Ignores development broadcast logs
6+
broadcast/
7+
!/broadcast
8+
/broadcast/*/31337/
9+
/broadcast/**/dry-run/
10+
11+
# Docs
12+
docs/
13+
14+
# Dotenv file
15+
.env
16+
17+
node_modules
18+
.env
19+
20+
# Hardhat files
21+
/cache
22+
23+
# TypeChain files
24+
/typechain
25+
/typechain-types
26+
27+
# solidity-coverage files
28+
/coverage
29+
/coverage.json
30+
31+
# Hardhat Ignition default folder for deployments against a local node
32+
ignition/deployments/chain-31337

Tiltfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
local_resource(
2+
"send-token-upgrade-deploy",
3+
cmd = os.path.join(__file__, "..", "bin", "anvil-deploy"),
4+
resource_deps = [
5+
"anvil:base",
6+
],
7+
)
8+

bin/anvil-deploy

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bun run
2+
import "zx/globals";
3+
$.verbose = true;
4+
5+
/**
6+
* This script is used to deploy the Send token lockbox contract.
7+
*/
8+
9+
const RPC_URL = "http://localhost:8546";
10+
const baseSendMVPDeployer = "0x7F314BffCB437b7046F469dE2457f9C4014931e1";
11+
12+
const info = (msg: TemplateStringsArray, ..._: any[]) =>
13+
console.log(chalk.blue(msg.join(" ")));
14+
15+
void (async function main() {
16+
info`Enable auto-mining...`;
17+
await $`cast rpc --rpc-url ${RPC_URL} evm_setAutomine true`;
18+
19+
info`Impersonating the Base Send MVP Deployer...`;
20+
await $`cast rpc --rpc-url ${RPC_URL} \
21+
anvil_impersonateAccount \
22+
${baseSendMVPDeployer}`;
23+
24+
info`Funding the Base Send MVP Deployer...`;
25+
await $`cast send --rpc-url ${RPC_URL} \
26+
--unlocked \
27+
--from 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
28+
${baseSendMVPDeployer} \
29+
--value 10ether`;
30+
31+
// remove previous deployments
32+
const artifactsDir = path.resolve(
33+
__dirname,
34+
"..",
35+
"ignition",
36+
"deployments",
37+
"chain-845337"
38+
);
39+
info`Removing previous deployments...`;
40+
await $`rm -rf ${artifactsDir}`;
41+
42+
info`Deploying SendLockbox...`;
43+
await $`echo yes | bunx hardhat ignition deploy --network anvil ./ignition/modules/SendToken.ts`;
44+
45+
info`Disable auto-mining...`;
46+
await $`cast rpc --rpc-url ${RPC_URL} evm_setAutomine false`;
47+
48+
info`Re-enable interval mining... ${$.env.ANVIL_BLOCK_TIME ?? "2"}`;
49+
await $`cast rpc --rpc-url ${RPC_URL} evm_setIntervalMining ${
50+
$.env.ANVIL_BLOCK_TIME ?? "2"
51+
}`; // mimics Tiltfile default
52+
53+
console.log(chalk.green("Done!"));
54+
})();

bunfig.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[install.scopes]
2+
"0xsend" = { token = "$npm_token", url = "https://registry.npmjs.org/" }

contracts/ISendLockbox.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: Apache 2
2+
pragma solidity ^0.8.28;
3+
4+
interface ISendLockbox {
5+
event Deposit(address indexed to, uint256 amount);
6+
7+
function deposit(uint256 amount) external;
8+
function depositTo(address to, uint256 amount) external;
9+
}

contracts/ISendToken.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: Apache 2
2+
pragma solidity ^0.8.28;
3+
4+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
6+
interface ISendToken is IERC20 {
7+
function mint(address to, uint256 amount) external;
8+
}

contracts/SendLockbox.sol

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
5+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6+
7+
import "./ISendToken.sol";
8+
import "./ISendLockbox.sol";
9+
10+
contract SendLockbox is ISendLockbox {
11+
using SafeERC20 for IERC20;
12+
13+
/// @notice The old ERC20 token of this contract
14+
IERC20 public immutable SEND_V0;
15+
16+
/// @notice The new ERC20 token of this contract
17+
ISendToken public immutable SEND_V1;
18+
19+
/// @param sendv0 The address of the old ERC20 contract
20+
/// @param sendv1 The address of the new ERC20 contract
21+
constructor(address sendv0, address sendv1) {
22+
SEND_V0 = IERC20(sendv0);
23+
SEND_V1 = ISendToken(sendv1);
24+
}
25+
26+
/// @notice Deposit tokens into the lockbox and mints the new token to sender
27+
/// @param amount The amount of tokens to deposit
28+
function deposit(uint256 amount) external {
29+
_deposit(msg.sender, amount);
30+
}
31+
32+
/// @notice Deposit ERC20 tokens into the lockbox
33+
/// @param to The user who should received minted tokens
34+
/// @param amount The amount of tokens to deposit
35+
function depositTo(address to, uint256 amount) external {
36+
_deposit(to, amount);
37+
}
38+
39+
/// @notice Deposit tokens into the lockbox
40+
/// @param to The user who should received minted tokens
41+
/// @param amount The amount of tokens to deposit
42+
function _deposit(address to, uint256 amount) internal {
43+
SEND_V0.safeTransferFrom(msg.sender, address(this), amount);
44+
emit Deposit(to, amount);
45+
46+
/// @notice v0 token has 0 decimals, v1 token has 18 decimals, therefore we multiply by 1 ether
47+
/// @notice v0 token has 100B supply, v1 token has 1B supply, therefore divided by 100
48+
uint256 amountToMint = (amount * 1 ether) / 100;
49+
SEND_V1.mint(to, amountToMint);
50+
}
51+
}

contracts/SendToken.sol

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
5+
6+
/*
7+
8+
███████╗███████╗███╗ ██╗██████╗ ██╗████████╗
9+
██╔════╝██╔════╝████╗ ██║██╔══██╗ ██║╚══██╔══╝
10+
███████╗█████╗ ██╔██╗ ██║██║ ██║ ██║ ██║
11+
╚════██║██╔══╝ ██║╚██╗██║██║ ██║ ██║ ██║
12+
███████║███████╗██║ ╚████║██████╔╝ ██║ ██║
13+
╚══════╝╚══════╝╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝
14+
15+
*/
16+
contract SendToken is ERC20Burnable {
17+
address public immutable lockbox;
18+
19+
constructor(
20+
string memory _name,
21+
string memory _symbol,
22+
address _lockbox
23+
) ERC20(_name, _symbol) {
24+
require(_lockbox != address(0), "ZL");
25+
lockbox = _lockbox;
26+
}
27+
28+
function mint(address to, uint256 amount) external {
29+
require(msg.sender == lockbox, "NL");
30+
_mint(to, amount);
31+
}
32+
}

0 commit comments

Comments
 (0)