mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-24 15:55:14 +00:00
add missing files on bbgo contract folder
This commit is contained in:
parent
a29198f733
commit
3717148b7a
17
contracts/.eslintrc.js
Normal file
17
contracts/.eslintrc.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
module.exports = {
|
||||||
|
parser: 'babel-eslint',
|
||||||
|
extends: 'standard',
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
es6: true,
|
||||||
|
mocha: true
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'space-before-function-paren': ['error', 'never']
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
contract: true,
|
||||||
|
web3: true,
|
||||||
|
assert: true
|
||||||
|
}
|
||||||
|
}
|
8
contracts/.solhint.json
Normal file
8
contracts/.solhint.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "solhint:recommended",
|
||||||
|
"plugins": [],
|
||||||
|
"rules": {
|
||||||
|
"compiler-version": ["error", ">=0.6.6"],
|
||||||
|
"reason-string": ["warn", {"maxLength": 64}]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,51 @@
|
||||||
|
# BBG Contracts
|
||||||
|
------------
|
||||||
|
|
||||||
|
### 1. Before Start
|
||||||
|
|
||||||
truffle migrate --network polygon
|
Create and modify the following files in this directory, the secret key inside the files are dummy ones from truffle dev server:
|
||||||
|
- development-secret.json
|
||||||
|
- polygon-secret.json
|
||||||
|
- bsc-secret.json
|
||||||
|
|
||||||
|
### 2. Prepare the dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm i
|
||||||
|
# if you want to develope in localhost, try to run npm run devserver separately
|
||||||
|
# ex: npm run devserver
|
||||||
|
# it will give you a set of secrets and account addresses
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Deploy
|
||||||
|
|
||||||
|
Migrate:
|
||||||
|
```bash
|
||||||
|
npm run migrate:dev
|
||||||
|
# npm run migrate:polygon
|
||||||
|
# npm run migrate:polygon-test
|
||||||
|
# npm run migrate:bsc
|
||||||
|
# npm run migrate:bsc-test
|
||||||
|
```
|
||||||
|
|
||||||
|
Lint:
|
||||||
|
```bash
|
||||||
|
npm run lint
|
||||||
|
# # fix solidity issue
|
||||||
|
# npm run lint:sol:fix
|
||||||
|
# # fix js issue
|
||||||
|
# npm run lint:js:fix
|
||||||
|
```
|
||||||
|
|
||||||
|
Test:
|
||||||
|
```bash
|
||||||
|
npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
truffle run verify ChildMintableERC20 --network polygon
|
truffle run verify ChildMintableERC20 --network polygon
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
truffle run verify ChildMintableERC20@0x3Afe98235d680e8d7A52e1458a59D60f45F935C0 --network polygon
|
truffle run verify ChildMintableERC20@0x3Afe98235d680e8d7A52e1458a59D60f45F935C0 --network polygon
|
||||||
|
```
|
||||||
|
|
4
contracts/bsc-secret.json
Normal file
4
contracts/bsc-secret.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"privateKey": "3899a918953e01bfe218116cdfeccbed579e26275c4a89abcbc70d2cb9e9bbb8",
|
||||||
|
"etherScanApiKey": ""
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity >=0.4.22 <0.9.0;
|
pragma solidity >=0.4.22 <0.9.0;
|
||||||
|
|
||||||
|
|
||||||
contract Migrations {
|
contract Migrations {
|
||||||
address public owner = msg.sender;
|
address public owner = msg.sender;
|
||||||
uint public last_completed_migration;
|
uint public last_completed_migration;
|
||||||
|
|
79
contracts/contracts/child/ChildToken/ChildMintableERC20.sol
Normal file
79
contracts/contracts/child/ChildToken/ChildMintableERC20.sol
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
|
import {AccessControlMixin} from "../../common/AccessControlMixin.sol";
|
||||||
|
import {IChildToken} from "./IChildToken.sol";
|
||||||
|
import {NativeMetaTransaction} from "../../common/NativeMetaTransaction.sol";
|
||||||
|
import {ContextMixin} from "../../common/ContextMixin.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract ChildMintableERC20 is
|
||||||
|
ERC20,
|
||||||
|
IChildToken,
|
||||||
|
AccessControlMixin,
|
||||||
|
NativeMetaTransaction,
|
||||||
|
ContextMixin
|
||||||
|
{
|
||||||
|
bytes32 public constant DEPOSITOR_ROLE = keccak256("DEPOSITOR_ROLE");
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
string memory name_,
|
||||||
|
string memory symbol_,
|
||||||
|
uint8 decimals_,
|
||||||
|
address childChainManager
|
||||||
|
) public ERC20(name_, symbol_) {
|
||||||
|
_setupContractId("ChildMintableERC20");
|
||||||
|
_setupDecimals(decimals_);
|
||||||
|
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
|
||||||
|
_setupRole(DEPOSITOR_ROLE, childChainManager);
|
||||||
|
_initializeEIP712(name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is to support Native meta transactions
|
||||||
|
// never use msg.sender directly, use _msgSender() instead
|
||||||
|
function _msgSender()
|
||||||
|
internal
|
||||||
|
override
|
||||||
|
view
|
||||||
|
returns (address payable sender)
|
||||||
|
{
|
||||||
|
return ContextMixin.msgSender();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice called when token is deposited on root chain
|
||||||
|
* @dev Should be callable only by ChildChainManager
|
||||||
|
* Should handle deposit by minting the required amount for user
|
||||||
|
* Make sure minting is done only by this function
|
||||||
|
* @param user user address for whom deposit is being done
|
||||||
|
* @param depositData abi encoded amount
|
||||||
|
*/
|
||||||
|
function deposit(address user, bytes calldata depositData)
|
||||||
|
external
|
||||||
|
override
|
||||||
|
only(DEPOSITOR_ROLE)
|
||||||
|
{
|
||||||
|
uint256 amount = abi.decode(depositData, (uint256));
|
||||||
|
_mint(user, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice called when user wants to withdraw tokens back to root chain
|
||||||
|
* @dev Should burn user's tokens. This transaction will be verified when exiting on root chain
|
||||||
|
* @param amount amount of tokens to withdraw
|
||||||
|
*/
|
||||||
|
function withdraw(uint256 amount) external {
|
||||||
|
_burn(_msgSender(), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Example function to handle minting tokens on matic chain
|
||||||
|
* @dev Minting can be done as per requirement,
|
||||||
|
* This implementation allows only admin to mint tokens but it can be changed as per requirement
|
||||||
|
* @param user user for whom tokens are being minted
|
||||||
|
* @param amount amount of token to mint
|
||||||
|
*/
|
||||||
|
function mint(address user, uint256 amount) public only(DEFAULT_ADMIN_ROLE) {
|
||||||
|
_mint(user, amount);
|
||||||
|
}
|
||||||
|
}
|
5
contracts/contracts/child/ChildToken/IChildToken.sol
Normal file
5
contracts/contracts/child/ChildToken/IChildToken.sol
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
interface IChildToken {
|
||||||
|
function deposit(address user, bytes calldata depositData) external;
|
||||||
|
}
|
19
contracts/contracts/common/AccessControlMixin.sol
Normal file
19
contracts/contracts/common/AccessControlMixin.sol
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract AccessControlMixin is AccessControl {
|
||||||
|
string private _revertMsg;
|
||||||
|
function _setupContractId(string memory contractId) internal {
|
||||||
|
_revertMsg = string(abi.encodePacked(contractId, ": INSUFFICIENT_PERMISSIONS"));
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier only(bytes32 role) {
|
||||||
|
require(
|
||||||
|
hasRole(role, _msgSender()),
|
||||||
|
_revertMsg
|
||||||
|
);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
25
contracts/contracts/common/ContextMixin.sol
Normal file
25
contracts/contracts/common/ContextMixin.sol
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
abstract contract ContextMixin {
|
||||||
|
function msgSender()
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (address payable sender)
|
||||||
|
{
|
||||||
|
if (msg.sender == address(this)) {
|
||||||
|
bytes memory array = msg.data;
|
||||||
|
uint256 index = msg.data.length;
|
||||||
|
/* solhint-disable no-inline-assembly */
|
||||||
|
assembly {
|
||||||
|
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
|
||||||
|
sender := and(
|
||||||
|
mload(add(array, index)),
|
||||||
|
0xffffffffffffffffffffffffffffffffffffffff
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender = msg.sender;
|
||||||
|
}
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
}
|
77
contracts/contracts/common/EIP712Base.sol
Normal file
77
contracts/contracts/common/EIP712Base.sol
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
import {Initializable} from "./Initializable.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract EIP712Base is Initializable {
|
||||||
|
struct EIP712Domain {
|
||||||
|
string name;
|
||||||
|
string version;
|
||||||
|
address verifyingContract;
|
||||||
|
bytes32 salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
string constant public ERC712_VERSION = "1";
|
||||||
|
|
||||||
|
bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256(
|
||||||
|
bytes(
|
||||||
|
"EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
bytes32 internal domainSeperator;
|
||||||
|
|
||||||
|
// supposed to be called once while initializing.
|
||||||
|
// one of the contractsa that inherits this contract follows proxy pattern
|
||||||
|
// so it is not possible to do this in a constructor
|
||||||
|
function _initializeEIP712(
|
||||||
|
string memory name
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
initializer
|
||||||
|
{
|
||||||
|
_setDomainSeperator(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setDomainSeperator(string memory name) internal {
|
||||||
|
domainSeperator = keccak256(
|
||||||
|
abi.encode(
|
||||||
|
EIP712_DOMAIN_TYPEHASH,
|
||||||
|
keccak256(bytes(name)),
|
||||||
|
keccak256(bytes(ERC712_VERSION)),
|
||||||
|
address(this),
|
||||||
|
bytes32(getChainId())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDomainSeperator() public view returns (bytes32) {
|
||||||
|
return domainSeperator;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChainId() public pure returns (uint256) {
|
||||||
|
uint256 id;
|
||||||
|
/* solhint-disable no-inline-assembly */
|
||||||
|
assembly {
|
||||||
|
id := chainid()
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept message hash and returns hash message in EIP712 compatible form
|
||||||
|
* So that it can be used to recover signer from signature signed using EIP712 formatted data
|
||||||
|
* https://eips.ethereum.org/EIPS/eip-712
|
||||||
|
* "\\x19" makes the encoding deterministic
|
||||||
|
* "\\x01" is the version byte to make it compatible to EIP-191
|
||||||
|
*/
|
||||||
|
function toTypedMessageHash(bytes32 messageHash)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
keccak256(
|
||||||
|
abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
12
contracts/contracts/common/Initializable.sol
Normal file
12
contracts/contracts/common/Initializable.sol
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
|
||||||
|
contract Initializable {
|
||||||
|
bool public inited = false;
|
||||||
|
|
||||||
|
modifier initializer() {
|
||||||
|
require(!inited, "already inited");
|
||||||
|
_;
|
||||||
|
inited = true;
|
||||||
|
}
|
||||||
|
}
|
106
contracts/contracts/common/NativeMetaTransaction.sol
Normal file
106
contracts/contracts/common/NativeMetaTransaction.sol
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";
|
||||||
|
import {EIP712Base} from "./EIP712Base.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract NativeMetaTransaction is EIP712Base {
|
||||||
|
using SafeMath for uint256;
|
||||||
|
bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256(
|
||||||
|
bytes(
|
||||||
|
"MetaTransaction(uint256 nonce,address from,bytes functionSignature)"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
event MetaTransactionExecuted(
|
||||||
|
address userAddress,
|
||||||
|
address payable relayerAddress,
|
||||||
|
bytes functionSignature
|
||||||
|
);
|
||||||
|
mapping(address => uint256) public nonces;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Meta transaction structure.
|
||||||
|
* No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
|
||||||
|
* He should call the desired function directly in that case.
|
||||||
|
*/
|
||||||
|
struct MetaTransaction {
|
||||||
|
uint256 nonce;
|
||||||
|
address from;
|
||||||
|
bytes functionSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeMetaTransaction(
|
||||||
|
address userAddress,
|
||||||
|
bytes memory functionSignature,
|
||||||
|
bytes32 sigR,
|
||||||
|
bytes32 sigS,
|
||||||
|
uint8 sigV
|
||||||
|
) public payable returns (bytes memory) {
|
||||||
|
MetaTransaction memory metaTx = MetaTransaction({
|
||||||
|
nonce: nonces[userAddress],
|
||||||
|
from: userAddress,
|
||||||
|
functionSignature: functionSignature
|
||||||
|
});
|
||||||
|
|
||||||
|
require(
|
||||||
|
verify(userAddress, metaTx, sigR, sigS, sigV),
|
||||||
|
"Signer and signature do not match"
|
||||||
|
);
|
||||||
|
|
||||||
|
// increase nonce for user (to avoid re-use)
|
||||||
|
nonces[userAddress] = nonces[userAddress].add(1);
|
||||||
|
|
||||||
|
emit MetaTransactionExecuted(
|
||||||
|
userAddress,
|
||||||
|
msg.sender,
|
||||||
|
functionSignature
|
||||||
|
);
|
||||||
|
|
||||||
|
// Append userAddress and relayer address at the end to extract it from calling context
|
||||||
|
/* solhint-disable avoid-low-level-calls */
|
||||||
|
(bool success, bytes memory returnData) = address(this).call(
|
||||||
|
abi.encodePacked(functionSignature, userAddress)
|
||||||
|
);
|
||||||
|
require(success, "Function call not successful");
|
||||||
|
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hashMetaTransaction(MetaTransaction memory metaTx)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
keccak256(
|
||||||
|
abi.encode(
|
||||||
|
META_TRANSACTION_TYPEHASH,
|
||||||
|
metaTx.nonce,
|
||||||
|
metaTx.from,
|
||||||
|
keccak256(metaTx.functionSignature)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNonce(address user) public view returns (uint256 nonce) {
|
||||||
|
nonce = nonces[user];
|
||||||
|
}
|
||||||
|
|
||||||
|
function verify(
|
||||||
|
address signer,
|
||||||
|
MetaTransaction memory metaTx,
|
||||||
|
bytes32 sigR,
|
||||||
|
bytes32 sigS,
|
||||||
|
uint8 sigV
|
||||||
|
) internal view returns (bool) {
|
||||||
|
require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER");
|
||||||
|
return
|
||||||
|
signer ==
|
||||||
|
ecrecover(
|
||||||
|
toTypedMessageHash(hashMetaTransaction(metaTx)),
|
||||||
|
sigV,
|
||||||
|
sigR,
|
||||||
|
sigS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
7
contracts/contracts/common/Proxy/IERCProxy.sol
Normal file
7
contracts/contracts/common/Proxy/IERCProxy.sol
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
interface IERCProxy {
|
||||||
|
function proxyType() external pure returns (uint256 proxyTypeId);
|
||||||
|
|
||||||
|
function implementation() external view returns (address codeAddr);
|
||||||
|
}
|
39
contracts/contracts/common/Proxy/Proxy.sol
Normal file
39
contracts/contracts/common/Proxy/Proxy.sol
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
import {IERCProxy} from "./IERCProxy.sol";
|
||||||
|
|
||||||
|
abstract contract Proxy is IERCProxy {
|
||||||
|
function delegatedFwd(address _dst, bytes memory _calldata) internal {
|
||||||
|
// solium-disable-next-line security/no-inline-assembly
|
||||||
|
assembly {
|
||||||
|
let result := delegatecall(
|
||||||
|
sub(gas(), 10000),
|
||||||
|
_dst,
|
||||||
|
add(_calldata, 0x20),
|
||||||
|
mload(_calldata),
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
let size := returndatasize()
|
||||||
|
|
||||||
|
let ptr := mload(0x40)
|
||||||
|
returndatacopy(ptr, 0, size)
|
||||||
|
|
||||||
|
// revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
|
||||||
|
// if the call returned error data, forward it
|
||||||
|
switch result
|
||||||
|
case 0 {
|
||||||
|
revert(ptr, size)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
return(ptr, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function proxyType() external virtual override pure returns (uint256 proxyTypeId) {
|
||||||
|
// Upgradeable proxy
|
||||||
|
proxyTypeId = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function implementation() external virtual override view returns (address);
|
||||||
|
}
|
103
contracts/contracts/common/Proxy/UpgradableProxy.sol
Normal file
103
contracts/contracts/common/Proxy/UpgradableProxy.sol
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
pragma solidity 0.6.6;
|
||||||
|
|
||||||
|
import {Proxy} from "./Proxy.sol";
|
||||||
|
|
||||||
|
contract UpgradableProxy is Proxy {
|
||||||
|
event ProxyUpdated(address indexed _new, address indexed _old);
|
||||||
|
event ProxyOwnerUpdate(address _new, address _old);
|
||||||
|
|
||||||
|
bytes32 constant IMPLEMENTATION_SLOT = keccak256("matic.network.proxy.implementation");
|
||||||
|
bytes32 constant OWNER_SLOT = keccak256("matic.network.proxy.owner");
|
||||||
|
|
||||||
|
constructor(address _proxyTo) public {
|
||||||
|
setProxyOwner(msg.sender);
|
||||||
|
setImplementation(_proxyTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback() external payable {
|
||||||
|
delegatedFwd(loadImplementation(), msg.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
receive() external payable {
|
||||||
|
delegatedFwd(loadImplementation(), msg.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier onlyProxyOwner() {
|
||||||
|
require(loadProxyOwner() == msg.sender, "NOT_OWNER");
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function proxyOwner() external view returns(address) {
|
||||||
|
return loadProxyOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadProxyOwner() internal view returns(address) {
|
||||||
|
address _owner;
|
||||||
|
bytes32 position = OWNER_SLOT;
|
||||||
|
assembly {
|
||||||
|
_owner := sload(position)
|
||||||
|
}
|
||||||
|
return _owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
function implementation() external override view returns (address) {
|
||||||
|
return loadImplementation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadImplementation() internal view returns(address) {
|
||||||
|
address _impl;
|
||||||
|
bytes32 position = IMPLEMENTATION_SLOT;
|
||||||
|
assembly {
|
||||||
|
_impl := sload(position)
|
||||||
|
}
|
||||||
|
return _impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferProxyOwnership(address newOwner) public onlyProxyOwner {
|
||||||
|
require(newOwner != address(0), "ZERO_ADDRESS");
|
||||||
|
emit ProxyOwnerUpdate(newOwner, loadProxyOwner());
|
||||||
|
setProxyOwner(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setProxyOwner(address newOwner) private {
|
||||||
|
bytes32 position = OWNER_SLOT;
|
||||||
|
assembly {
|
||||||
|
sstore(position, newOwner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateImplementation(address _newProxyTo) public onlyProxyOwner {
|
||||||
|
require(_newProxyTo != address(0x0), "INVALID_PROXY_ADDRESS");
|
||||||
|
require(isContract(_newProxyTo), "DESTINATION_ADDRESS_IS_NOT_A_CONTRACT");
|
||||||
|
|
||||||
|
emit ProxyUpdated(_newProxyTo, loadImplementation());
|
||||||
|
|
||||||
|
setImplementation(_newProxyTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAndCall(address _newProxyTo, bytes memory data) payable public onlyProxyOwner {
|
||||||
|
updateImplementation(_newProxyTo);
|
||||||
|
|
||||||
|
(bool success, bytes memory returnData) = address(this).call{value: msg.value}(data);
|
||||||
|
require(success, string(returnData));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setImplementation(address _newProxyTo) private {
|
||||||
|
bytes32 position = IMPLEMENTATION_SLOT;
|
||||||
|
assembly {
|
||||||
|
sstore(position, _newProxyTo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isContract(address _target) internal view returns (bool) {
|
||||||
|
if (_target == address(0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 size;
|
||||||
|
assembly {
|
||||||
|
size := extcodesize(_target)
|
||||||
|
}
|
||||||
|
return size > 0;
|
||||||
|
}
|
||||||
|
}
|
4
contracts/development-secret.json
Normal file
4
contracts/development-secret.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"privateKey": "3899a918953e01bfe218116cdfeccbed579e26275c4a89abcbc70d2cb9e9bbb8",
|
||||||
|
"etherScanApiKey": ""
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
var ChildMintableERC20 = artifacts.require("./ChildMintableERC20.sol");
|
var ChildMintableERC20 = artifacts.require("ChildMintableERC20");
|
||||||
|
|
||||||
module.exports = function(deployer) {
|
module.exports = function(deployer) {
|
||||||
deployer.deploy(ChildMintableERC20, 'BBGO', 'BBG', 18, '0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa');
|
deployer.deploy(ChildMintableERC20, 'BBGO', 'BBG', 18, '0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa');
|
||||||
|
|
32452
contracts/package-lock.json
generated
Normal file
32452
contracts/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -17,11 +17,24 @@
|
||||||
"ethereum-waffle": "^3.4.0",
|
"ethereum-waffle": "^3.4.0",
|
||||||
"ethers": "^5.4.7",
|
"ethers": "^5.4.7",
|
||||||
"hardhat": "^2.6.5",
|
"hardhat": "^2.6.5",
|
||||||
|
"prettier": "^2.5.1",
|
||||||
|
"solhint": "^3.3.6",
|
||||||
"truffle-plugin-verify": "^0.5.18"
|
"truffle-plugin-verify": "^0.5.18"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha"
|
"devserver": "KEY=development-secret.json truffle develop",
|
||||||
|
"test": "KEY=development-secret.json truffle test",
|
||||||
|
"migrate:dev": "KEY=development-secret.json truffle migrate --network development",
|
||||||
|
"migrate:polygon": "KEY=polygon-secret.json truffle migrate --network polygon",
|
||||||
|
"migrate:polygon-test": "KEY=polygon-secret.json truffle migrate --network mumbai",
|
||||||
|
"migrate:bsc": "KEY=bsc-secret.json truffle migrate --network bsc",
|
||||||
|
"migrate:bsc-test": "KEY=bsc-secret.json truffle migrate --network bsctestnet",
|
||||||
|
"lint": "npm run lint:sol && npm run lint:js",
|
||||||
|
"lint:js:fix": "prettier --write test/**/*.js",
|
||||||
|
"lint:js": "prettier test/**/*.js",
|
||||||
|
"lint:sol": "solhint contracts/**/*.sol",
|
||||||
|
"lint:sol:fix": "solhint -d contracts/**/*.sol --fix"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "starcrypto",
|
||||||
"license": "ISC"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
|
|
4
contracts/polygon-secret.json
Normal file
4
contracts/polygon-secret.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"privateKey": "3899a918953e01bfe218116cdfeccbed579e26275c4a89abcbc70d2cb9e9bbb8",
|
||||||
|
"etherScanApiKey": ""
|
||||||
|
}
|
16
contracts/test/erc20.js
Normal file
16
contracts/test/erc20.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
const ChildMintableERC20 = artifacts.require("ChildMintableERC20");
|
||||||
|
contract("ChildMintableERC20", (accounts) => {
|
||||||
|
it("should have BBG deployed", async () => {
|
||||||
|
const instance = await ChildMintableERC20.deployed();
|
||||||
|
const name = await instance.name();
|
||||||
|
const decimal = await instance.decimals();
|
||||||
|
const symbol = await instance.symbol();
|
||||||
|
const balance = await instance.balanceOf(accounts[0]);
|
||||||
|
const totalSupply = await instance.totalSupply();
|
||||||
|
assert.equal(name.valueOf(), "BBGO");
|
||||||
|
assert.equal(symbol.valueOf(), "BBG");
|
||||||
|
assert.equal(decimal.toNumber(), 18);
|
||||||
|
assert.equal(balance.toNumber(), 0);
|
||||||
|
assert.equal(totalSupply.toNumber(), 0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -19,7 +19,8 @@
|
||||||
*/
|
*/
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const HDWalletProvider = require('@truffle/hdwallet-provider');
|
const HDWalletProvider = require('@truffle/hdwallet-provider');
|
||||||
const secret = JSON.parse(fs.readFileSync("polygon-secret.json").toString().trim());
|
const secret = JSON.parse(fs.readFileSync(process.env.KEY).toString().trim());
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
|
@ -69,19 +70,38 @@ module.exports = {
|
||||||
// network_id: 2111, // This network is yours, in the cloud.
|
// network_id: 2111, // This network is yours, in the cloud.
|
||||||
// production: true // Treats this network as if it was a public net. (default: false)
|
// production: true // Treats this network as if it was a public net. (default: false)
|
||||||
// }
|
// }
|
||||||
|
development: {
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 9545,
|
||||||
|
network_id: "*",
|
||||||
|
},
|
||||||
polygon: {
|
polygon: {
|
||||||
provider: () => new HDWalletProvider(secret.privateKey, "https://polygon-rpc.com"),
|
provider: () => new HDWalletProvider(secret.privateKey, "https://polygon-rpc.com"),
|
||||||
network_id: 137,
|
network_id: 137,
|
||||||
confirmations: 3,
|
confirmations: 3,
|
||||||
timeoutBlocks: 200,
|
timeoutBlocks: 200,
|
||||||
skipDryRun: true
|
skipDryRun: true
|
||||||
},
|
},
|
||||||
mumbai: {
|
mumbai: {
|
||||||
provider: () => new HDWalletProvider(secret.privateKey, "https://matic-mumbai.chainstacklabs.com"),
|
provider: () => new HDWalletProvider(secret.privateKey, "https://matic-mumbai.chainstacklabs.com"),
|
||||||
network_id: 80001,
|
network_id: 80001,
|
||||||
confirmations: 3,
|
confirmations: 3,
|
||||||
timeoutBlocks: 200,
|
timeoutBlocks: 200,
|
||||||
skipDryRun: true
|
skipDryRun: true
|
||||||
|
},
|
||||||
|
bsctestnet: {
|
||||||
|
// "https://speedy-nodes-nyc.moralis.io/91d001d6e2a55a9696521b4b/bsc/testnet"
|
||||||
|
provider: () => new HDWalletProvider(secret.privateKey, "https://data-seed-prebsc-1-s1.binance.org:8545"),
|
||||||
|
network_id: 97,
|
||||||
|
confirmations: 10,
|
||||||
|
timeoutBlocks: 200,
|
||||||
|
},
|
||||||
|
bsc: {
|
||||||
|
provider: () => new HDWalletProvider(secret.privateKey, "https://bsc-dataseed1.binance.org"),
|
||||||
|
network_id: 56,
|
||||||
|
confirmations: 10,
|
||||||
|
timeoutBlocks: 200,
|
||||||
|
skipDryRun: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user