Skip to content

Commit e11467b

Browse files
committedAug 4, 2023
feat: added a PNK faucet on ArbitrumGoerli
1 parent 4854782 commit e11467b

File tree

7 files changed

+614
-5
lines changed

7 files changed

+614
-5
lines changed
 

‎contracts/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments
3434
- [DisputeResolver](https://goerli.arbiscan.io/address/0xcDC05c8d2EEEe384359Bd22E8631528B6b0564e9)
3535
- [HomeGatewayToGnosis](https://goerli.arbiscan.io/address/0x1807b0049D412a3208d840D74725e404a55E297E)
3636
- [KlerosCore](https://goerli.arbiscan.io/address/0x8Af82E2F8890acb4AB84cbaB3c4C4Eb3E965CF24)
37-
- [PNKFaucet](https://goerli.arbiscan.io/address/0xcc9dA0E6Fe98934781A57C861C939AC36989990d)
37+
- [PNKFaucet](https://goerli.arbiscan.io/address/0x120C48fcB2343ccCD4Fa4Dc81CF48fcf8538bFc9)
3838
- [PolicyRegistry](https://goerli.arbiscan.io/address/0xED503aBA65B28D81444294D1eAa5d84CeFdC2C58)
3939
- [RandomizerRNG](https://goerli.arbiscan.io/address/0xa90f7D2e35718FDE9AD96c8B6667AFcAa4BEfd4d)
4040
- [SortitionModule](https://goerli.arbiscan.io/address/0x5Ae75Db8B66B574b2c5C29eE4D32cc9Fe62bfdEE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { HardhatRuntimeEnvironment } from "hardhat/types";
2+
import { DeployFunction } from "hardhat-deploy/types";
3+
4+
enum HomeChains {
5+
ARBITRUM_ONE = 42161,
6+
ARBITRUM_GOERLI = 421613,
7+
HARDHAT = 31337,
8+
}
9+
10+
const pnkByChain = new Map<HomeChains, string>([
11+
[HomeChains.ARBITRUM_ONE, "0x330bD769382cFc6d50175903434CCC8D206DCAE5"],
12+
[HomeChains.ARBITRUM_GOERLI, "0x4DEeeFD054434bf6721eF39Aa18EfB3fd0D12610"],
13+
]);
14+
15+
const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
16+
const { ethers, deployments, getNamedAccounts, getChainId } = hre;
17+
const { deploy, execute } = deployments;
18+
19+
// fallback to hardhat node signers on local network
20+
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
21+
const chainId = Number(await getChainId());
22+
console.log("Deploying to %s with deployer %s", HomeChains[chainId], deployer);
23+
24+
const pnkAddress = pnkByChain.get(chainId);
25+
if (pnkAddress) {
26+
await deploy("PNKFaucet", {
27+
from: deployer,
28+
contract: "Faucet",
29+
args: [pnkAddress],
30+
log: true,
31+
});
32+
await execute(
33+
"PNKFaucet",
34+
{ from: deployer, log: true },
35+
"changeAmount",
36+
hre.ethers.utils.parseUnits("200", "ether")
37+
);
38+
}
39+
};
40+
41+
deployArbitration.tags = ["PnkFaucet"];
42+
deployArbitration.skip = async ({ getChainId }) => {
43+
const chainId = Number(await getChainId());
44+
return !HomeChains[chainId];
45+
};
46+
47+
export default deployArbitration;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
{
2+
"address": "0x82C3FF40B0DB79b84bB97Df7792D759bDfAD1eAb",
3+
"abi": [
4+
{
5+
"inputs": [
6+
{
7+
"internalType": "contract IERC20",
8+
"name": "_token",
9+
"type": "address"
10+
}
11+
],
12+
"stateMutability": "nonpayable",
13+
"type": "constructor"
14+
},
15+
{
16+
"inputs": [],
17+
"name": "balance",
18+
"outputs": [
19+
{
20+
"internalType": "uint256",
21+
"name": "",
22+
"type": "uint256"
23+
}
24+
],
25+
"stateMutability": "view",
26+
"type": "function"
27+
},
28+
{
29+
"inputs": [],
30+
"name": "request",
31+
"outputs": [],
32+
"stateMutability": "nonpayable",
33+
"type": "function"
34+
},
35+
{
36+
"inputs": [],
37+
"name": "token",
38+
"outputs": [
39+
{
40+
"internalType": "contract IERC20",
41+
"name": "",
42+
"type": "address"
43+
}
44+
],
45+
"stateMutability": "view",
46+
"type": "function"
47+
},
48+
{
49+
"inputs": [
50+
{
51+
"internalType": "address",
52+
"name": "",
53+
"type": "address"
54+
}
55+
],
56+
"name": "withdrewAlready",
57+
"outputs": [
58+
{
59+
"internalType": "bool",
60+
"name": "",
61+
"type": "bool"
62+
}
63+
],
64+
"stateMutability": "view",
65+
"type": "function"
66+
}
67+
],
68+
"transactionHash": "0x3244db77e66f3d61edaf6deac6e02748941599043f12979d09ee3ec25cf65637",
69+
"receipt": {
70+
"to": null,
71+
"from": "0xF50E77f2A2B6138D16c6c7511562E5C33c4B15A3",
72+
"contractAddress": "0x82C3FF40B0DB79b84bB97Df7792D759bDfAD1eAb",
73+
"transactionIndex": 1,
74+
"gasUsed": "24605280",
75+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
76+
"blockHash": "0xe4134560c265e638a9cebce6dd4b8ee3e1824a6ad841654e8c4942c62d214644",
77+
"transactionHash": "0x3244db77e66f3d61edaf6deac6e02748941599043f12979d09ee3ec25cf65637",
78+
"logs": [],
79+
"blockNumber": 28787588,
80+
"cumulativeGasUsed": "24605280",
81+
"status": 1,
82+
"byzantium": true
83+
},
84+
"args": [
85+
"0x70A704Dce4cCC00568Cc142C86D07Ec71C944a39"
86+
],
87+
"numDeployments": 1,
88+
"solcInputHash": "961befc2fb36daa22c7c449f4b260d32",
89+
"metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_token\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"request\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"withdrewAlready\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/token/Faucet.sol\":\"Faucet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"src/token/Faucet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract Faucet {\\n IERC20 public token;\\n mapping(address => bool) public withdrewAlready;\\n\\n constructor(IERC20 _token) {\\n token = _token;\\n }\\n\\n function balance() public view returns (uint) {\\n return token.balanceOf(address(this));\\n }\\n\\n function request() public {\\n require(\\n !withdrewAlready[msg.sender],\\n \\\"You have used this faucet already. If you need more tokens, please use another address.\\\"\\n );\\n token.transfer(msg.sender, 10000 ether);\\n withdrewAlready[msg.sender] = true;\\n }\\n}\\n\",\"keccak256\":\"0xac876a15a73b0ab2161f4e42850028fbc6db4a899f83052c0d4f97050b2d1650\",\"license\":\"MIT\"}},\"version\":1}",
90+
"bytecode": "0x608060405234801561001057600080fd5b506040516103c23803806103c283398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b61032f806100936000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063338cdca114610051578063b69ef8a81461005b578063d61c40dc14610076578063fc0c546a146100a9575b600080fd5b6100596100d4565b005b61006361021c565b6040519081526020015b60405180910390f35b61009961008436600461028e565b60016020526000908152604090205460ff1681565b604051901515815260200161006d565b6000546100bc906001600160a01b031681565b6040516001600160a01b03909116815260200161006d565b3360009081526001602052604090205460ff161561017e5760405162461bcd60e51b815260206004820152605760248201527f596f752068617665207573656420746869732066617563657420616c7265616460448201527f792e20496620796f75206e656564206d6f726520746f6b656e732c20706c656160648201527639b2903ab9b29030b737ba3432b91030b2323932b9b99760491b608482015260a40160405180910390fd5b60005460405163a9059cbb60e01b815233600482015269021e19e0c9bab240000060248201526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc91906102be565b50336000908152600160208190526040909120805460ff19169091179055565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610265573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028991906102e0565b905090565b6000602082840312156102a057600080fd5b81356001600160a01b03811681146102b757600080fd5b9392505050565b6000602082840312156102d057600080fd5b815180151581146102b757600080fd5b6000602082840312156102f257600080fd5b505191905056fea2646970667358221220885a998acda2ccef49efd5707e9579a53bbed80122cfef4ce320a92f34aba57664736f6c63430008120033",
91+
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063338cdca114610051578063b69ef8a81461005b578063d61c40dc14610076578063fc0c546a146100a9575b600080fd5b6100596100d4565b005b61006361021c565b6040519081526020015b60405180910390f35b61009961008436600461028e565b60016020526000908152604090205460ff1681565b604051901515815260200161006d565b6000546100bc906001600160a01b031681565b6040516001600160a01b03909116815260200161006d565b3360009081526001602052604090205460ff161561017e5760405162461bcd60e51b815260206004820152605760248201527f596f752068617665207573656420746869732066617563657420616c7265616460448201527f792e20496620796f75206e656564206d6f726520746f6b656e732c20706c656160648201527639b2903ab9b29030b737ba3432b91030b2323932b9b99760491b608482015260a40160405180910390fd5b60005460405163a9059cbb60e01b815233600482015269021e19e0c9bab240000060248201526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc91906102be565b50336000908152600160208190526040909120805460ff19169091179055565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610265573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028991906102e0565b905090565b6000602082840312156102a057600080fd5b81356001600160a01b03811681146102b757600080fd5b9392505050565b6000602082840312156102d057600080fd5b815180151581146102b757600080fd5b6000602082840312156102f257600080fd5b505191905056fea2646970667358221220885a998acda2ccef49efd5707e9579a53bbed80122cfef4ce320a92f34aba57664736f6c63430008120033",
92+
"devdoc": {
93+
"kind": "dev",
94+
"methods": {},
95+
"version": 1
96+
},
97+
"userdoc": {
98+
"kind": "user",
99+
"methods": {},
100+
"version": 1
101+
},
102+
"storageLayout": {
103+
"storage": [
104+
{
105+
"astId": 21616,
106+
"contract": "src/token/Faucet.sol:Faucet",
107+
"label": "token",
108+
"offset": 0,
109+
"slot": "0",
110+
"type": "t_contract(IERC20)929"
111+
},
112+
{
113+
"astId": 21620,
114+
"contract": "src/token/Faucet.sol:Faucet",
115+
"label": "withdrewAlready",
116+
"offset": 0,
117+
"slot": "1",
118+
"type": "t_mapping(t_address,t_bool)"
119+
}
120+
],
121+
"types": {
122+
"t_address": {
123+
"encoding": "inplace",
124+
"label": "address",
125+
"numberOfBytes": "20"
126+
},
127+
"t_bool": {
128+
"encoding": "inplace",
129+
"label": "bool",
130+
"numberOfBytes": "1"
131+
},
132+
"t_contract(IERC20)929": {
133+
"encoding": "inplace",
134+
"label": "contract IERC20",
135+
"numberOfBytes": "20"
136+
},
137+
"t_mapping(t_address,t_bool)": {
138+
"encoding": "mapping",
139+
"key": "t_address",
140+
"label": "mapping(address => bool)",
141+
"numberOfBytes": "32",
142+
"value": "t_bool"
143+
}
144+
}
145+
}
146+
}

‎contracts/deployments/arbitrumGoerli/PNKFaucet.json

+226
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
{
2+
"address": "0x87Efe303Cbc866320c14805C4D6cd04f426FBB17",
3+
"abi": [
4+
{
5+
"inputs": [
6+
{
7+
"internalType": "contract IERC20",
8+
"name": "_token",
9+
"type": "address"
10+
}
11+
],
12+
"stateMutability": "nonpayable",
13+
"type": "constructor"
14+
},
15+
{
16+
"inputs": [],
17+
"name": "balance",
18+
"outputs": [
19+
{
20+
"internalType": "uint256",
21+
"name": "",
22+
"type": "uint256"
23+
}
24+
],
25+
"stateMutability": "view",
26+
"type": "function"
27+
},
28+
{
29+
"inputs": [],
30+
"name": "request",
31+
"outputs": [],
32+
"stateMutability": "nonpayable",
33+
"type": "function"
34+
},
35+
{
36+
"inputs": [],
37+
"name": "token",
38+
"outputs": [
39+
{
40+
"internalType": "contract IERC20",
41+
"name": "",
42+
"type": "address"
43+
}
44+
],
45+
"stateMutability": "view",
46+
"type": "function"
47+
},
48+
{
49+
"inputs": [
50+
{
51+
"internalType": "address",
52+
"name": "",
53+
"type": "address"
54+
}
55+
],
56+
"name": "withdrewAlready",
57+
"outputs": [
58+
{
59+
"internalType": "bool",
60+
"name": "",
61+
"type": "bool"
62+
}
63+
],
64+
"stateMutability": "view",
65+
"type": "function"
66+
}
67+
],
68+
"transactionHash": "0x0824d11ff39320da58048400c0e9fc03a58a58558f105a2fcd6ccd0380fa3f1a",
69+
"receipt": {
70+
"to": null,
71+
"from": "0xF50E77f2A2B6138D16c6c7511562E5C33c4B15A3",
72+
"contractAddress": "0x87Efe303Cbc866320c14805C4D6cd04f426FBB17",
73+
"transactionIndex": 1,
74+
"gasUsed": "24579067",
75+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
76+
"blockHash": "0x0c6e933e8407a173fb809c58991275a69c7f0f9282a693a36a05d964509cf6f5",
77+
"transactionHash": "0x0824d11ff39320da58048400c0e9fc03a58a58558f105a2fcd6ccd0380fa3f1a",
78+
"logs": [],
79+
"blockNumber": 28787590,
80+
"cumulativeGasUsed": "24579067",
81+
"status": 1,
82+
"byzantium": true
83+
},
84+
"args": [
85+
"0xddE1b84E43505432Fdf5F810ebB9373dD37e9230"
86+
],
87+
"numDeployments": 1,
88+
"solcInputHash": "961befc2fb36daa22c7c449f4b260d32",
89+
"metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_token\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"request\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"withdrewAlready\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/token/Faucet.sol\":\"Faucet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"src/token/Faucet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract Faucet {\\n IERC20 public token;\\n mapping(address => bool) public withdrewAlready;\\n\\n constructor(IERC20 _token) {\\n token = _token;\\n }\\n\\n function balance() public view returns (uint) {\\n return token.balanceOf(address(this));\\n }\\n\\n function request() public {\\n require(\\n !withdrewAlready[msg.sender],\\n \\\"You have used this faucet already. If you need more tokens, please use another address.\\\"\\n );\\n token.transfer(msg.sender, 10000 ether);\\n withdrewAlready[msg.sender] = true;\\n }\\n}\\n\",\"keccak256\":\"0xac876a15a73b0ab2161f4e42850028fbc6db4a899f83052c0d4f97050b2d1650\",\"license\":\"MIT\"}},\"version\":1}",
90+
"bytecode": "0x608060405234801561001057600080fd5b506040516103c23803806103c283398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b61032f806100936000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063338cdca114610051578063b69ef8a81461005b578063d61c40dc14610076578063fc0c546a146100a9575b600080fd5b6100596100d4565b005b61006361021c565b6040519081526020015b60405180910390f35b61009961008436600461028e565b60016020526000908152604090205460ff1681565b604051901515815260200161006d565b6000546100bc906001600160a01b031681565b6040516001600160a01b03909116815260200161006d565b3360009081526001602052604090205460ff161561017e5760405162461bcd60e51b815260206004820152605760248201527f596f752068617665207573656420746869732066617563657420616c7265616460448201527f792e20496620796f75206e656564206d6f726520746f6b656e732c20706c656160648201527639b2903ab9b29030b737ba3432b91030b2323932b9b99760491b608482015260a40160405180910390fd5b60005460405163a9059cbb60e01b815233600482015269021e19e0c9bab240000060248201526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc91906102be565b50336000908152600160208190526040909120805460ff19169091179055565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610265573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028991906102e0565b905090565b6000602082840312156102a057600080fd5b81356001600160a01b03811681146102b757600080fd5b9392505050565b6000602082840312156102d057600080fd5b815180151581146102b757600080fd5b6000602082840312156102f257600080fd5b505191905056fea2646970667358221220885a998acda2ccef49efd5707e9579a53bbed80122cfef4ce320a92f34aba57664736f6c63430008120033",
91+
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063338cdca114610051578063b69ef8a81461005b578063d61c40dc14610076578063fc0c546a146100a9575b600080fd5b6100596100d4565b005b61006361021c565b6040519081526020015b60405180910390f35b61009961008436600461028e565b60016020526000908152604090205460ff1681565b604051901515815260200161006d565b6000546100bc906001600160a01b031681565b6040516001600160a01b03909116815260200161006d565b3360009081526001602052604090205460ff161561017e5760405162461bcd60e51b815260206004820152605760248201527f596f752068617665207573656420746869732066617563657420616c7265616460448201527f792e20496620796f75206e656564206d6f726520746f6b656e732c20706c656160648201527639b2903ab9b29030b737ba3432b91030b2323932b9b99760491b608482015260a40160405180910390fd5b60005460405163a9059cbb60e01b815233600482015269021e19e0c9bab240000060248201526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc91906102be565b50336000908152600160208190526040909120805460ff19169091179055565b600080546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610265573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028991906102e0565b905090565b6000602082840312156102a057600080fd5b81356001600160a01b03811681146102b757600080fd5b9392505050565b6000602082840312156102d057600080fd5b815180151581146102b757600080fd5b6000602082840312156102f257600080fd5b505191905056fea2646970667358221220885a998acda2ccef49efd5707e9579a53bbed80122cfef4ce320a92f34aba57664736f6c63430008120033",
92+
"devdoc": {
93+
"kind": "dev",
94+
"methods": {},
95+
"version": 1
96+
},
97+
"userdoc": {
98+
"kind": "user",
99+
"methods": {},
100+
"version": 1
101+
},
102+
"storageLayout": {
103+
"storage": [
104+
{
105+
"astId": 21616,
106+
"contract": "src/token/Faucet.sol:Faucet",
107+
"label": "token",
108+
"offset": 0,
109+
"slot": "0",
110+
"type": "t_contract(IERC20)929"
111+
},
112+
{
113+
"astId": 21620,
114+
"contract": "src/token/Faucet.sol:Faucet",
115+
"label": "withdrewAlready",
116+
"offset": 0,
117+
"slot": "1",
118+
"type": "t_mapping(t_address,t_bool)"
119+
}
120+
],
121+
"types": {
122+
"t_address": {
123+
"encoding": "inplace",
124+
"label": "address",
125+
"numberOfBytes": "20"
126+
},
127+
"t_bool": {
128+
"encoding": "inplace",
129+
"label": "bool",
130+
"numberOfBytes": "1"
131+
},
132+
"t_contract(IERC20)929": {
133+
"encoding": "inplace",
134+
"label": "contract IERC20",
135+
"numberOfBytes": "20"
136+
},
137+
"t_mapping(t_address,t_bool)": {
138+
"encoding": "mapping",
139+
"key": "t_address",
140+
"label": "mapping(address => bool)",
141+
"numberOfBytes": "32",
142+
"value": "t_bool"
143+
}
144+
}
145+
}
146+
}

‎contracts/scripts/generateDeploymentsMarkdown.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
55
function generate() { #deploymentDir #explorerUrl
66
deploymentDir=$1
77
explorerUrl=$2
8-
for f in $(ls -1 $deploymentDir/*.json | grep -v "PNK.json\|MetaEvidence_*"); do
8+
for f in $(ls -1 $deploymentDir/*.json | grep -v "PNK.json\|MetaEvidence_*\|CREATE3Factory.json" | sort); do
99
contractName=$(basename $f .json)
1010
address=$(cat $f | jq -r .address)
1111
echo "- [$contractName]($explorerUrl$address)"

‎contracts/src/token/Faucet.sol

+47-3
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,67 @@ pragma solidity 0.8.18;
55
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
66

77
contract Faucet {
8+
// ************************************* //
9+
// * Storage * //
10+
// ************************************* //
11+
812
IERC20 public token;
13+
address public governor;
914
mapping(address => bool) public withdrewAlready;
15+
uint256 public amount = 10_000 ether;
16+
17+
// ************************************* //
18+
// * Function Modifiers * //
19+
// ************************************* //
20+
21+
modifier onlyByGovernor() {
22+
require(address(governor) == msg.sender, "Access not allowed: Governor only.");
23+
_;
24+
}
25+
26+
// ************************************* //
27+
// * Constructor * //
28+
// ************************************* //
1029

1130
constructor(IERC20 _token) {
1231
token = _token;
32+
governor = msg.sender;
1333
}
1434

15-
function balance() public view returns (uint) {
16-
return token.balanceOf(address(this));
35+
// ************************************* //
36+
// * Governance * //
37+
// ************************************* //
38+
39+
function changeGovernor(address _governor) public onlyByGovernor {
40+
governor = _governor;
41+
}
42+
43+
function changeAmount(uint256 _amount) public onlyByGovernor {
44+
amount = _amount;
45+
}
46+
47+
function withdraw() public onlyByGovernor {
48+
token.transfer(governor, token.balanceOf(address(this)));
1749
}
1850

51+
// ************************************* //
52+
// * State Modifiers * //
53+
// ************************************* //
54+
1955
function request() public {
2056
require(
2157
!withdrewAlready[msg.sender],
2258
"You have used this faucet already. If you need more tokens, please use another address."
2359
);
24-
token.transfer(msg.sender, 10000 ether);
60+
token.transfer(msg.sender, amount);
2561
withdrewAlready[msg.sender] = true;
2662
}
63+
64+
// ************************************* //
65+
// * Public Views * //
66+
// ************************************* //
67+
68+
function balance() public view returns (uint) {
69+
return token.balanceOf(address(this));
70+
}
2771
}

0 commit comments

Comments
 (0)
Please sign in to comment.