commit
9e41dba391
@ -0,0 +1,11 @@ |
|||||||
|
node_modules |
||||||
|
.env |
||||||
|
coverage |
||||||
|
coverage.json |
||||||
|
typechain |
||||||
|
typechain-types |
||||||
|
|
||||||
|
# Hardhat files |
||||||
|
cache |
||||||
|
artifacts |
||||||
|
|
@ -0,0 +1,99 @@ |
|||||||
|
# Kaly Chain wKLC Token & Vesting Contract Deploy and Verify |
||||||
|
|
||||||
|
## How to configue `harhat.config.js` |
||||||
|
|
||||||
|
```bash |
||||||
|
module.exports = { |
||||||
|
solidity: { |
||||||
|
compilers: [ |
||||||
|
{ |
||||||
|
version: "0.8.11", |
||||||
|
settings: { |
||||||
|
optimizer: { |
||||||
|
enabled: true, |
||||||
|
runs: 200, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
], |
||||||
|
}, |
||||||
|
networks: { |
||||||
|
kaly: { |
||||||
|
url: "https://testnetrpc.kalychain.io/rpc", |
||||||
|
accounts: ['put your private key here dont forget to remove before uploading to github'], |
||||||
|
gas: 3000000, |
||||||
|
gasPrice: 8000000000, |
||||||
|
|
||||||
|
} |
||||||
|
}, |
||||||
|
etherscan: { |
||||||
|
apiKey: { |
||||||
|
kaly: "abc" |
||||||
|
}, |
||||||
|
customChains: [ |
||||||
|
{ |
||||||
|
network: "kaly", |
||||||
|
chainId: 3889, |
||||||
|
allowUnlimitedContractSize: true, |
||||||
|
gas: 3000000, |
||||||
|
gasPrice: 8000000000, |
||||||
|
urls: { |
||||||
|
apiURL: "https://testnet.kalyscan.io/api", |
||||||
|
browserURL: "https://testnet.kalyscan.io" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}; |
||||||
|
``` |
||||||
|
|
||||||
|
## How to deploy wKLC token and Vesting contract |
||||||
|
|
||||||
|
### Deploy token contract |
||||||
|
|
||||||
|
```bash |
||||||
|
npx hardhat run scripts/deploy_token.js --network kaly |
||||||
|
``` |
||||||
|
|
||||||
|
### Deploy token vesting contract |
||||||
|
|
||||||
|
Before deploy, you have to update `scripts/deploy_vesting.js` as you can see below with the wKLC address. |
||||||
|
|
||||||
|
```bash |
||||||
|
const TokenVesting = await ethers.getContractFactory("TokenVesting"); |
||||||
|
const tokenVesting = await TokenVesting.deploy( |
||||||
|
Token = "0x069255299Bb729399f3CECaBdc73d15d3D10a2A3" |
||||||
|
); |
||||||
|
console.log("TokenVesting address:", tokenVesting.address); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
```bash |
||||||
|
npx hardhat run scripts/deploy_vesting.js --network kaly |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Update `scripts/verify_vesting.js` with the Token Vesting address and wKLC address |
||||||
|
|
||||||
|
`verify_vesting.js` |
||||||
|
```bash |
||||||
|
await hre.run("verify:verify", { |
||||||
|
address: Deployed Token Vesting contract address, |
||||||
|
constructorArguments: [ |
||||||
|
0x069255299Bb729399f3CECaBdc73d15d3D10a2A3 |
||||||
|
] |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
The final step is run below commands. |
||||||
|
|
||||||
|
```bash |
||||||
|
npx hardhat run scripts/verify_token.js --network kaly |
||||||
|
``` |
||||||
|
|
||||||
|
```bash |
||||||
|
npx hardhat run scripts/verify_vesting.js --network kaly |
||||||
|
``` |
||||||
|
|
||||||
|
|
||||||
|
Finally, you will get fully verified wKLC Token and Vesting contracts. |
@ -0,0 +1,351 @@ |
|||||||
|
// contracts/TokenVesting.sol |
||||||
|
// SPDX-License-Identifier: Apache-2.0 |
||||||
|
pragma solidity 0.8.11; |
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; |
||||||
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; |
||||||
|
import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; |
||||||
|
import "@openzeppelin/contracts/access/Ownable.sol"; |
||||||
|
import "@openzeppelin/contracts/utils/math/Math.sol"; |
||||||
|
import "@openzeppelin/contracts/utils/math/SafeMath.sol"; |
||||||
|
|
||||||
|
/** |
||||||
|
* @title TokenVesting |
||||||
|
*/ |
||||||
|
contract TokenVesting is Ownable, ReentrancyGuard{ |
||||||
|
using SafeMath for uint256; |
||||||
|
using SafeERC20 for IERC20; |
||||||
|
struct VestingSchedule{ |
||||||
|
bool initialized; |
||||||
|
// beneficiary of tokens after they are released |
||||||
|
address beneficiary; |
||||||
|
// cliff period in seconds |
||||||
|
uint256 cliff; |
||||||
|
// start time of the vesting period |
||||||
|
uint256 start; |
||||||
|
// duration of the vesting period in seconds |
||||||
|
uint256 duration; |
||||||
|
// duration of a slice period for the vesting in seconds |
||||||
|
uint256 slicePeriodSeconds; |
||||||
|
// whether or not the vesting is revocable |
||||||
|
bool revocable; |
||||||
|
// total amount of tokens to be released at the end of the vesting |
||||||
|
uint256 amountTotal; |
||||||
|
// amount of tokens released |
||||||
|
uint256 released; |
||||||
|
// whether or not the vesting has been revoked |
||||||
|
bool revoked; |
||||||
|
} |
||||||
|
|
||||||
|
// address of the ERC20 token |
||||||
|
IERC20 immutable private _token; |
||||||
|
|
||||||
|
bytes32[] private vestingSchedulesIds; |
||||||
|
mapping(bytes32 => VestingSchedule) private vestingSchedules; |
||||||
|
uint256 private vestingSchedulesTotalAmount; |
||||||
|
mapping(address => uint256) private holdersVestingCount; |
||||||
|
|
||||||
|
event Released(uint256 amount); |
||||||
|
event Revoked(); |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Reverts if no vesting schedule matches the passed identifier. |
||||||
|
*/ |
||||||
|
modifier onlyIfVestingScheduleExists(bytes32 vestingScheduleId) { |
||||||
|
require(vestingSchedules[vestingScheduleId].initialized == true); |
||||||
|
_; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Reverts if the vesting schedule does not exist or has been revoked. |
||||||
|
*/ |
||||||
|
modifier onlyIfVestingScheduleNotRevoked(bytes32 vestingScheduleId) { |
||||||
|
require(vestingSchedules[vestingScheduleId].initialized == true); |
||||||
|
require(vestingSchedules[vestingScheduleId].revoked == false); |
||||||
|
_; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Creates a vesting contract. |
||||||
|
* @param token_ address of the ERC20 token contract |
||||||
|
*/ |
||||||
|
constructor(address token_) { |
||||||
|
require(token_ != address(0x0)); |
||||||
|
_token = IERC20(token_); |
||||||
|
} |
||||||
|
|
||||||
|
receive() external payable {} |
||||||
|
|
||||||
|
fallback() external payable {} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Returns the number of vesting schedules associated to a beneficiary. |
||||||
|
* @return the number of vesting schedules |
||||||
|
*/ |
||||||
|
function getVestingSchedulesCountByBeneficiary(address _beneficiary) |
||||||
|
external |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
return holdersVestingCount[_beneficiary]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Returns the vesting schedule id at the given index. |
||||||
|
* @return the vesting id |
||||||
|
*/ |
||||||
|
function getVestingIdAtIndex(uint256 index) |
||||||
|
external |
||||||
|
view |
||||||
|
returns(bytes32){ |
||||||
|
require(index < getVestingSchedulesCount(), "TokenVesting: index out of bounds"); |
||||||
|
return vestingSchedulesIds[index]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Returns the vesting schedule information for a given holder and index. |
||||||
|
* @return the vesting schedule structure information |
||||||
|
*/ |
||||||
|
function getVestingScheduleByAddressAndIndex(address holder, uint256 index) |
||||||
|
external |
||||||
|
view |
||||||
|
returns(VestingSchedule memory){ |
||||||
|
return getVestingSchedule(computeVestingScheduleIdForAddressAndIndex(holder, index)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Returns the total amount of vesting schedules. |
||||||
|
* @return the total amount of vesting schedules |
||||||
|
*/ |
||||||
|
function getVestingSchedulesTotalAmount() |
||||||
|
external |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
return vestingSchedulesTotalAmount; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Returns the address of the ERC20 token managed by the vesting contract. |
||||||
|
*/ |
||||||
|
function getToken() |
||||||
|
external |
||||||
|
view |
||||||
|
returns(address){ |
||||||
|
return address(_token); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Creates a new vesting schedule for a beneficiary. |
||||||
|
* @param _beneficiary address of the beneficiary to whom vested tokens are transferred |
||||||
|
* @param _start start time of the vesting period |
||||||
|
* @param _cliff duration in seconds of the cliff in which tokens will begin to vest |
||||||
|
* @param _duration duration in seconds of the period in which the tokens will vest |
||||||
|
* @param _slicePeriodSeconds duration of a slice period for the vesting in seconds |
||||||
|
* @param _revocable whether the vesting is revocable or not |
||||||
|
* @param _amount total amount of tokens to be released at the end of the vesting |
||||||
|
*/ |
||||||
|
function createVestingSchedule( |
||||||
|
address _beneficiary, |
||||||
|
uint256 _start, |
||||||
|
uint256 _cliff, |
||||||
|
uint256 _duration, |
||||||
|
uint256 _slicePeriodSeconds, |
||||||
|
bool _revocable, |
||||||
|
uint256 _amount |
||||||
|
) |
||||||
|
public |
||||||
|
onlyOwner{ |
||||||
|
require( |
||||||
|
this.getWithdrawableAmount() >= _amount, |
||||||
|
"TokenVesting: cannot create vesting schedule because not sufficient tokens" |
||||||
|
); |
||||||
|
require(_duration > 0, "TokenVesting: duration must be > 0"); |
||||||
|
require(_amount > 0, "TokenVesting: amount must be > 0"); |
||||||
|
require(_slicePeriodSeconds >= 1, "TokenVesting: slicePeriodSeconds must be >= 1"); |
||||||
|
bytes32 vestingScheduleId = this.computeNextVestingScheduleIdForHolder(_beneficiary); |
||||||
|
uint256 cliff = _start.add(_cliff); |
||||||
|
vestingSchedules[vestingScheduleId] = VestingSchedule( |
||||||
|
true, |
||||||
|
_beneficiary, |
||||||
|
cliff, |
||||||
|
_start, |
||||||
|
_duration, |
||||||
|
_slicePeriodSeconds, |
||||||
|
_revocable, |
||||||
|
_amount, |
||||||
|
0, |
||||||
|
false |
||||||
|
); |
||||||
|
vestingSchedulesTotalAmount = vestingSchedulesTotalAmount.add(_amount); |
||||||
|
vestingSchedulesIds.push(vestingScheduleId); |
||||||
|
uint256 currentVestingCount = holdersVestingCount[_beneficiary]; |
||||||
|
holdersVestingCount[_beneficiary] = currentVestingCount.add(1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Revokes the vesting schedule for given identifier. |
||||||
|
* @param vestingScheduleId the vesting schedule identifier |
||||||
|
*/ |
||||||
|
function revoke(bytes32 vestingScheduleId) |
||||||
|
public |
||||||
|
onlyOwner |
||||||
|
onlyIfVestingScheduleNotRevoked(vestingScheduleId){ |
||||||
|
VestingSchedule storage vestingSchedule = vestingSchedules[vestingScheduleId]; |
||||||
|
require(vestingSchedule.revocable == true, "TokenVesting: vesting is not revocable"); |
||||||
|
uint256 vestedAmount = _computeReleasableAmount(vestingSchedule); |
||||||
|
if(vestedAmount > 0){ |
||||||
|
release(vestingScheduleId, vestedAmount); |
||||||
|
} |
||||||
|
uint256 unreleased = vestingSchedule.amountTotal.sub(vestingSchedule.released); |
||||||
|
vestingSchedulesTotalAmount = vestingSchedulesTotalAmount.sub(unreleased); |
||||||
|
vestingSchedule.revoked = true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Withdraw the specified amount if possible. |
||||||
|
* @param amount the amount to withdraw |
||||||
|
*/ |
||||||
|
function withdraw(uint256 amount) |
||||||
|
public |
||||||
|
nonReentrant |
||||||
|
onlyOwner{ |
||||||
|
require(this.getWithdrawableAmount() >= amount, "TokenVesting: not enough withdrawable funds"); |
||||||
|
_token.safeTransfer(owner(), amount); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Release vested amount of tokens. |
||||||
|
* @param vestingScheduleId the vesting schedule identifier |
||||||
|
* @param amount the amount to release |
||||||
|
*/ |
||||||
|
function release( |
||||||
|
bytes32 vestingScheduleId, |
||||||
|
uint256 amount |
||||||
|
) |
||||||
|
public |
||||||
|
nonReentrant |
||||||
|
onlyIfVestingScheduleNotRevoked(vestingScheduleId){ |
||||||
|
VestingSchedule storage vestingSchedule = vestingSchedules[vestingScheduleId]; |
||||||
|
bool isBeneficiary = msg.sender == vestingSchedule.beneficiary; |
||||||
|
bool isOwner = msg.sender == owner(); |
||||||
|
require( |
||||||
|
isBeneficiary || isOwner, |
||||||
|
"TokenVesting: only beneficiary and owner can release vested tokens" |
||||||
|
); |
||||||
|
uint256 vestedAmount = _computeReleasableAmount(vestingSchedule); |
||||||
|
require(vestedAmount >= amount, "TokenVesting: cannot release tokens, not enough vested tokens"); |
||||||
|
vestingSchedule.released = vestingSchedule.released.add(amount); |
||||||
|
address payable beneficiaryPayable = payable(vestingSchedule.beneficiary); |
||||||
|
vestingSchedulesTotalAmount = vestingSchedulesTotalAmount.sub(amount); |
||||||
|
_token.safeTransfer(beneficiaryPayable, amount); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Returns the number of vesting schedules managed by this contract. |
||||||
|
* @return the number of vesting schedules |
||||||
|
*/ |
||||||
|
function getVestingSchedulesCount() |
||||||
|
public |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
return vestingSchedulesIds.length; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Computes the vested amount of tokens for the given vesting schedule identifier. |
||||||
|
* @return the vested amount |
||||||
|
*/ |
||||||
|
function computeReleasableAmount(bytes32 vestingScheduleId) |
||||||
|
public |
||||||
|
onlyIfVestingScheduleNotRevoked(vestingScheduleId) |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
VestingSchedule storage vestingSchedule = vestingSchedules[vestingScheduleId]; |
||||||
|
return _computeReleasableAmount(vestingSchedule); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @notice Returns the vesting schedule information for a given identifier. |
||||||
|
* @return the vesting schedule structure information |
||||||
|
*/ |
||||||
|
function getVestingSchedule(bytes32 vestingScheduleId) |
||||||
|
public |
||||||
|
view |
||||||
|
returns(VestingSchedule memory){ |
||||||
|
return vestingSchedules[vestingScheduleId]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Returns the amount of tokens that can be withdrawn by the owner. |
||||||
|
* @return the amount of tokens |
||||||
|
*/ |
||||||
|
function getWithdrawableAmount() |
||||||
|
public |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
return _token.balanceOf(address(this)).sub(vestingSchedulesTotalAmount); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Computes the next vesting schedule identifier for a given holder address. |
||||||
|
*/ |
||||||
|
function computeNextVestingScheduleIdForHolder(address holder) |
||||||
|
public |
||||||
|
view |
||||||
|
returns(bytes32){ |
||||||
|
return computeVestingScheduleIdForAddressAndIndex(holder, holdersVestingCount[holder]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Returns the last vesting schedule for a given holder address. |
||||||
|
*/ |
||||||
|
function getLastVestingScheduleForHolder(address holder) |
||||||
|
public |
||||||
|
view |
||||||
|
returns(VestingSchedule memory){ |
||||||
|
return vestingSchedules[computeVestingScheduleIdForAddressAndIndex(holder, holdersVestingCount[holder] - 1)]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Computes the vesting schedule identifier for an address and an index. |
||||||
|
*/ |
||||||
|
function computeVestingScheduleIdForAddressAndIndex(address holder, uint256 index) |
||||||
|
public |
||||||
|
pure |
||||||
|
returns(bytes32){ |
||||||
|
return keccak256(abi.encodePacked(holder, index)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dev Computes the releasable amount of tokens for a vesting schedule. |
||||||
|
* @return the amount of releasable tokens |
||||||
|
*/ |
||||||
|
function _computeReleasableAmount(VestingSchedule memory vestingSchedule) |
||||||
|
internal |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
uint256 currentTime = getCurrentTime(); |
||||||
|
if ((currentTime < vestingSchedule.cliff) || vestingSchedule.revoked == true) { |
||||||
|
return 0; |
||||||
|
} else if (currentTime >= vestingSchedule.start.add(vestingSchedule.duration)) { |
||||||
|
return vestingSchedule.amountTotal.sub(vestingSchedule.released); |
||||||
|
} else { |
||||||
|
uint256 timeFromStart = currentTime.sub(vestingSchedule.start); |
||||||
|
uint secondsPerSlice = vestingSchedule.slicePeriodSeconds; |
||||||
|
uint256 vestedSlicePeriods = timeFromStart.div(secondsPerSlice); |
||||||
|
uint256 vestedSeconds = vestedSlicePeriods.mul(secondsPerSlice); |
||||||
|
uint256 vestedAmount = vestingSchedule.amountTotal.mul(vestedSeconds).div(vestingSchedule.duration); |
||||||
|
vestedAmount = vestedAmount.sub(vestingSchedule.released); |
||||||
|
return vestedAmount; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function getCurrentTime() |
||||||
|
internal |
||||||
|
virtual |
||||||
|
view |
||||||
|
returns(uint256){ |
||||||
|
return block.timestamp; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
// SPDX-License-Identifier: MIT |
||||||
|
pragma solidity ^0.8.0; |
||||||
|
|
||||||
|
contract WKLC { |
||||||
|
string public name = "Wrapped Kaly Coin"; |
||||||
|
string public symbol = "WKLC"; |
||||||
|
uint8 public decimals = 18; |
||||||
|
mapping (address => uint256) public balanceOf; |
||||||
|
mapping (address => mapping (address => uint256)) public allowance; |
||||||
|
|
||||||
|
event Approval(address indexed src, address indexed guy, uint256 wad); |
||||||
|
event Transfer(address indexed src, address indexed dst, uint256 wad); |
||||||
|
event Deposit(address indexed dst, uint256 wad); |
||||||
|
event Withdrawal(address indexed src, uint256 wad); |
||||||
|
|
||||||
|
receive() external payable { |
||||||
|
deposit(); |
||||||
|
} |
||||||
|
|
||||||
|
function deposit() public payable { |
||||||
|
balanceOf[msg.sender] += msg.value; |
||||||
|
emit Deposit(msg.sender, msg.value); |
||||||
|
} |
||||||
|
|
||||||
|
function withdraw(uint256 wad) public { |
||||||
|
require(balanceOf[msg.sender] >= wad); |
||||||
|
balanceOf[msg.sender] -= wad; |
||||||
|
payable(msg.sender).transfer(wad); |
||||||
|
emit Withdrawal(msg.sender, wad); |
||||||
|
} |
||||||
|
|
||||||
|
function totalSupply() public view returns (uint256) { |
||||||
|
return address(this).balance; |
||||||
|
} |
||||||
|
|
||||||
|
function approve(address guy, uint256 wad) public returns (bool) { |
||||||
|
allowance[msg.sender][guy] = wad; |
||||||
|
emit Approval(msg.sender, guy, wad); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
function transfer(address dst, uint256 wad) public returns (bool) { |
||||||
|
return transferFrom(msg.sender, dst, wad); |
||||||
|
} |
||||||
|
|
||||||
|
function transferFrom(address src, address dst, uint256 wad) public returns (bool) { |
||||||
|
require(balanceOf[src] >= wad); |
||||||
|
|
||||||
|
if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { |
||||||
|
require(allowance[src][msg.sender] >= wad); |
||||||
|
allowance[src][msg.sender] -= wad; |
||||||
|
} |
||||||
|
|
||||||
|
balanceOf[src] -= wad; |
||||||
|
balanceOf[dst] += wad; |
||||||
|
|
||||||
|
emit Transfer(src, dst, wad); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
require("@nomicfoundation/hardhat-toolbox"); |
||||||
|
require("dotenv").config(); |
||||||
|
|
||||||
|
// This is a sample Hardhat task. To learn how to create your own go to
|
||||||
|
// https://hardhat.org/guides/create-task.html
|
||||||
|
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { |
||||||
|
const accounts = await hre.ethers.getSigners(); |
||||||
|
|
||||||
|
for (const account of accounts) { |
||||||
|
console.log(account.address); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// You need to export an object to set up your config
|
||||||
|
// Go to https://hardhat.org/config/ to learn more
|
||||||
|
|
||||||
|
/** |
||||||
|
* @type import('hardhat/config').HardhatUserConfig |
||||||
|
*/ |
||||||
|
module.exports = { |
||||||
|
solidity: { |
||||||
|
compilers: [ |
||||||
|
{ |
||||||
|
version: "0.8.11", |
||||||
|
settings: { |
||||||
|
optimizer: { |
||||||
|
enabled: true, |
||||||
|
runs: 200, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
], |
||||||
|
}, |
||||||
|
networks: { |
||||||
|
kaly: { |
||||||
|
url: "https://testnetrpc.kalychain.io/rpc", |
||||||
|
accounts: [''], |
||||||
|
gas: 3000000, |
||||||
|
gasPrice: 8000000000, |
||||||
|
|
||||||
|
} |
||||||
|
}, |
||||||
|
etherscan: { |
||||||
|
apiKey: { |
||||||
|
kaly: "abc" |
||||||
|
}, |
||||||
|
customChains: [ |
||||||
|
{ |
||||||
|
network: "kaly", |
||||||
|
chainId: 3889, |
||||||
|
allowUnlimitedContractSize: true, |
||||||
|
gas: 3000000, |
||||||
|
gasPrice: 8000000000, |
||||||
|
urls: { |
||||||
|
apiURL: "https://testnet.kalyscan.io/api", |
||||||
|
browserURL: "https://testnet.kalyscan.io" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}; |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@ |
|||||||
|
{ |
||||||
|
"name": "vesting", |
||||||
|
"version": "1.0.0", |
||||||
|
"description": "", |
||||||
|
"main": "index.js", |
||||||
|
"scripts": { |
||||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||||
|
}, |
||||||
|
"keywords": [], |
||||||
|
"author": "", |
||||||
|
"license": "ISC", |
||||||
|
"devDependencies": { |
||||||
|
"@nomicfoundation/hardhat-chai-matchers": "^1.0.5", |
||||||
|
"@nomicfoundation/hardhat-toolbox": "^2.0.0", |
||||||
|
"@nomiclabs/hardhat-ethers": "^2.2.1", |
||||||
|
"chai": "^4.3.7", |
||||||
|
"ethers": "^5.7.2", |
||||||
|
"hardhat": "^2.12.3" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"@openzeppelin/contracts": "^4.8.0", |
||||||
|
"@unirep/contracts": "^1.0.1", |
||||||
|
"dotenv": "^16.0.3" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
const main = async () => { |
||||||
|
const [deployer] = await hre.ethers.getSigners(); |
||||||
|
const accountBalance = await deployer.getBalance(); |
||||||
|
|
||||||
|
console.log("Deploying contracts with account: ", deployer.address); |
||||||
|
console.log("Account balance: ", accountBalance.toString()); |
||||||
|
|
||||||
|
const contractFactory = await hre.ethers.getContractFactory("WKLC"); |
||||||
|
const contract = await contractFactory.deploy(); |
||||||
|
await contract.deployed(); |
||||||
|
|
||||||
|
console.log("WKLC address: ", contract.address); |
||||||
|
}; |
||||||
|
|
||||||
|
const runMain = async () => { |
||||||
|
try { |
||||||
|
await main(); |
||||||
|
process.exit(0); |
||||||
|
} catch (error) { |
||||||
|
console.log(error); |
||||||
|
process.exit(1); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
runMain(); |
@ -0,0 +1,20 @@ |
|||||||
|
async function main() { |
||||||
|
const [deployer] = await ethers.getSigners(); |
||||||
|
|
||||||
|
console.log("Deploying contracts with the account:", deployer.address); |
||||||
|
|
||||||
|
console.log("Account balance:", (await deployer.getBalance()).toString()); |
||||||
|
|
||||||
|
const TokenVesting = await ethers.getContractFactory("TokenVesting"); |
||||||
|
const tokenVesting = await TokenVesting.deploy( |
||||||
|
Token = "0x069255299Bb729399f3CECaBdc73d15d3D10a2A3" |
||||||
|
); |
||||||
|
console.log("TokenVesting address:", tokenVesting.address); |
||||||
|
} |
||||||
|
|
||||||
|
main() |
||||||
|
.then(() => process.exit(0)) |
||||||
|
.catch((error) => { |
||||||
|
console.error(error); |
||||||
|
process.exit(1); |
||||||
|
}); |
@ -0,0 +1,17 @@ |
|||||||
|
const main = async () => { |
||||||
|
await hre.run("verify:verify", { |
||||||
|
address: "0xdaDbc4d96E5b418562d85DdAccBE970d0aca4803" |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
const runMain = async () => { |
||||||
|
try { |
||||||
|
await main(); |
||||||
|
process.exit(0); |
||||||
|
} catch (error) { |
||||||
|
console.log(error); |
||||||
|
process.exit(1); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
runMain(); |
@ -0,0 +1,20 @@ |
|||||||
|
const main = async () => { |
||||||
|
await hre.run("verify:verify", { |
||||||
|
address: "0x43D5576CF364eAc467Da4644C123C81A34DA1034", |
||||||
|
constructorArguments: [ |
||||||
|
"0x069255299Bb729399f3CECaBdc73d15d3D10a2A3" |
||||||
|
] |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
const runMain = async () => { |
||||||
|
try { |
||||||
|
await main(); |
||||||
|
process.exit(0); |
||||||
|
} catch (error) { |
||||||
|
console.log(error); |
||||||
|
process.exit(1); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
runMain(); |
Loading…
Reference in new issue