Merge pull request #530 from harmony-one/rj_branch

Add listLockedAddresses and add contract abi
pull/536/head
Rongjian Lan 6 years ago committed by GitHub
commit 45e38cbc2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      api/service/staking/service.go
  2. 143
      contracts/StakeLockContract.json
  3. 84
      contracts/StakeLockContract.sol

@ -3,8 +3,11 @@ package staking
import (
"crypto/ecdsa"
"math/big"
"os"
"time"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
@ -98,6 +101,14 @@ func (s *Service) IsStaked() bool {
// DoService does staking.
func (s *Service) DoService() {
utils.GetLogInstance().Info("Trying to send a staking transaction.")
abi, err := s.getStakeLockContractABI()
if err != nil {
utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err)
} else {
utils.GetLogInstance().Info("Generated staking contract's ABI", "abi", abi)
}
// TODO: use abi to generate staking transaction.
if s.beaconChain == nil {
utils.GetLogInstance().Info("Can not send a staking transaction because of nil beacon chain.")
return
@ -110,6 +121,17 @@ func (s *Service) DoService() {
}
}
func (s *Service) getStakeLockContractABI() (abi.ABI, error) {
f, err := os.Open("./contracts/StakeLockContract.json")
if err != nil {
if os.IsNotExist(err) {
return abi.ABI{}, err
}
}
defer f.Close()
return abi.JSON(f)
}
func (s *Service) getStakingInfo() *proto.StakingContractInfoResponse {
address := crypto.PubkeyToAddress(s.accountKey.PublicKey)
state, err := s.beaconChain.State()

@ -0,0 +1,143 @@
[
{
"constant": true,
"inputs": [],
"name": "listLockedAddresses",
"outputs": [
{
"name": "lockedAddresses",
"type": "address[]"
},
{
"name": "blockNums",
"type": "uint256[]"
},
{
"name": "lockPeriodCounts",
"type": "uint256[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_of",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "currentEpoch",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "unlock",
"outputs": [
{
"name": "unlockableTokens",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_of",
"type": "address"
}
],
"name": "getUnlockableTokens",
"outputs": [
{
"name": "unlockableTokens",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "lock",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": true,
"stateMutability": "payable",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_of",
"type": "address"
},
{
"indexed": false,
"name": "_amount",
"type": "uint256"
},
{
"indexed": false,
"name": "_epoch",
"type": "uint256"
}
],
"name": "Locked",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "account",
"type": "address"
},
{
"indexed": false,
"name": "index",
"type": "uint256"
}
],
"name": "Unlocked",
"type": "event"
}
]

@ -5,7 +5,7 @@ contract StakeLockContract {
* @dev Error messages for require statements
*/
string internal constant ALREADY_LOCKED = 'Tokens already locked';
string internal constant NOT_LOCKED = 'No tokens locked';
string internal constant NO_TOKEN_UNLOCKABLE = 'No tokens unlockable';
string internal constant AMOUNT_ZERO = 'Amount can not be 0';
uint256 internal constant LOCK_PERIOD_IN_EPOCHS = 3; // Final locking period TBD.
@ -16,10 +16,11 @@ contract StakeLockContract {
* @dev locked token structure
*/
struct lockedToken {
uint256 _amount;
uint256 _blockNum;
uint256 _epochNum;
uint256 _continueCount;
uint256 _amount; // The amount of token locked
uint256 _blockNum; // The number of the block when the token was locked
uint256 _epochNum; // The epoch when the token was locked
uint256 _lockPeriodCount; // The number of locking period the token will be locked.
uint256 _index; // The index in the addressList
}
/**
@ -28,62 +29,54 @@ contract StakeLockContract {
*/
mapping(address => lockedToken) private locked;
mapping(address => uint) private indices;
address[] private accountList;
address[] private addressList;
event Locked(address indexed _of, uint _amount, uint256 _epoch);
event Unlocked(address indexed account, uint index);
/**
* @dev Returns total tokens held by an address (locked + transferable)
* @param _of The address to query the total balance of
*/
function lockedBalanceOf(address _of)
public
view
returns (uint256 amount)
{
amount = locked[_of]._amount;
}
/**
* @dev Locks a specified amount of tokens against an address
* starting at the specific epoch
* @param _epoch The epoch where the lock happens
*/
function lock(uint256 _epoch)
function lock()
public
payable
returns (bool)
{
// If tokens are already locked, then functions extendLock or
// increaseLockAmount should be used to make any changes
require(lockedBalanceOf(msg.sender) == 0, ALREADY_LOCKED);
require(balanceOf(msg.sender) == 0, ALREADY_LOCKED);
require(msg.value != 0, AMOUNT_ZERO);
locked[msg.sender] = lockedToken(msg.value, block.number, currentEpoch(), 1);
// By default, the tokens can only be locked for one locking period.
locked[msg.sender] = lockedToken(msg.value, block.number, currentEpoch(), 1, addressList.push(msg.sender) - 1);
emit Locked(msg.sender, msg.value, _epoch);
emit Locked(msg.sender, msg.value, currentEpoch());
return true;
}
/**
* @dev Unlocks the unlockable tokens of a specified address
* @param _requestor Address of user, claiming back unlockable tokens
*/
function unlock(address payable _requestor)
function unlock()
public
returns (uint256 unlockableTokens)
{
unlockableTokens = getUnlockableTokens(_requestor);
unlockableTokens = getUnlockableTokens(msg.sender); // For now the unlockableTokens is all the tokens for a address
require(unlockableTokens != 0, NO_TOKEN_UNLOCKABLE);
if (unlockableTokens != 0) {
_requestor.transfer(unlockableTokens);
}
uint indexToRemove = locked[msg.sender]._index;
delete locked[msg.sender];
addressList[indexToRemove] = addressList[addressList.length - 1];
locked[addressList[addressList.length - 1]]._index = indexToRemove;
addressList.length--;
msg.sender.transfer(unlockableTokens);
}
/**
* @dev Gets the unlockable tokens of a specified address
* @param _of The address to query the the unlockable token count of
* @param _of The address to query the unlockable token
*/
function getUnlockableTokens(address _of)
public
@ -91,11 +84,23 @@ contract StakeLockContract {
returns (uint256 unlockableTokens)
{
uint256 currentEpoch = currentEpoch();
if (locked[_of]._epochNum + locked[_of]._continueCount * LOCK_PERIOD_IN_EPOCHS < currentEpoch) {
if (locked[_of]._epochNum + locked[_of]._lockPeriodCount * LOCK_PERIOD_IN_EPOCHS < currentEpoch) {
unlockableTokens = locked[_of]._amount;
}
}
/**
* @dev Gets the token balance of a specified address
* @param _of The address to query the token balance
*/
function balanceOf(address _of)
public
view
returns (uint256 balance)
{
balance = locked[_of]._amount;
}
/**
* @dev Gets the epoch number of the specified block number.
*/
@ -106,4 +111,21 @@ contract StakeLockContract {
{
return block.number / numBlocksPerEpoch;
}
/**
* @dev Lists all the locked address data.
*/
function listLockedAddresses()
public
view
returns (address[] memory lockedAddresses, uint256[] memory blockNums, uint256[] memory lockPeriodCounts)
{
lockedAddresses = addressList;
blockNums = new uint256[](addressList.length);
lockPeriodCounts = new uint256[](addressList.length);
for (uint i = 0; i < lockedAddresses.length; i++) {
blockNums[i] = locked[lockedAddresses[i]]._blockNum;
lockPeriodCounts[i] = locked[lockedAddresses[i]]._lockPeriodCount;
}
}
}

Loading…
Cancel
Save