Skip to content

Commit

Permalink
Enable contract to stake/sponsor (#1319)
Browse files Browse the repository at this point in the history
* enable contract to stake

* remove contract limit in sponsor

* forbid static call in internal contract

* fail unsupported function call of internal contract
  • Loading branch information
zimpha authored and Peilun Li committed Apr 20, 2020
1 parent a697730 commit ec5d697
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 27 deletions.
4 changes: 2 additions & 2 deletions core/src/executive/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,14 +313,14 @@ impl<'a> CallCreateExecutive<'a> {
)?;
state.new_contract_with_admin(
&params.address,
&params.sender,
&params.original_sender,
val + balance,
nonce_offset,
)?;
} else {
state.new_contract_with_admin(
&params.address,
&params.sender,
&params.original_sender,
balance,
nonce_offset,
)?;
Expand Down
8 changes: 6 additions & 2 deletions core/src/executive/internal_contract/impls/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
bytes::Bytes,
parameters::staking::*,
state::{CollateralCheckResult, State, Substate},
vm::{self, ActionParams, Spec},
vm::{self, ActionParams, CallType, Spec},
};
use cfx_types::{Address, U256};
use std::str::FromStr;
Expand Down Expand Up @@ -159,6 +159,10 @@ impl InternalContractTrait for AdminControl {
substate: &mut Substate,
) -> vm::Result<()>
{
if params.call_type == CallType::StaticCall {
return Err(vm::Error::MutableCallInStaticContext);
}

let data = if let Some(ref d) = params.data {
d as &[u8]
} else {
Expand Down Expand Up @@ -196,7 +200,7 @@ impl InternalContractTrait for AdminControl {
// 4 bytes 'Method ID` + 20 bytes `contract_address`
self.destroy(&data[4..], params, state, spec, substate)
} else {
Ok(())
Err(vm::Error::InternalContract("unsupported function"))
}
}
}
20 changes: 6 additions & 14 deletions core/src/executive/internal_contract/impls/sponsor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::super::InternalContractTrait;
use crate::{
bytes::Bytes,
state::{State, Substate},
vm::{self, ActionParams, Spec},
vm::{self, ActionParams, CallType, Spec},
};
use cfx_types::{Address, U256};
use std::str::FromStr;
Expand All @@ -24,12 +24,6 @@ impl SponsorWhitelistControl {
state: &mut State, substate: &mut Substate,
) -> vm::Result<()>
{
if state.is_contract(&params.sender) {
return Err(vm::Error::InternalContract(
"contract account is not allowed to sponsor other contract",
));
}

if input.len() != 64 {
return Err(vm::Error::InternalContract("invalid data"));
}
Expand Down Expand Up @@ -136,12 +130,6 @@ impl SponsorWhitelistControl {
state: &mut State, substate: &mut Substate,
) -> vm::Result<()>
{
if state.is_contract(&params.sender) {
return Err(vm::Error::InternalContract(
"contract account is not allowed to sponsor other contract",
));
}

if input.len() != 32 {
return Err(vm::Error::InternalContract("invalid data"));
}
Expand Down Expand Up @@ -310,6 +298,10 @@ impl InternalContractTrait for SponsorWhitelistControl {
substate: &mut Substate,
) -> vm::Result<()>
{
if params.call_type == CallType::StaticCall {
return Err(vm::Error::MutableCallInStaticContext);
}

let data = if let Some(ref d) = params.data {
d as &[u8]
} else {
Expand Down Expand Up @@ -356,7 +348,7 @@ impl InternalContractTrait for SponsorWhitelistControl {
// 4 bytes `Method ID` + 32 bytes location + 32 bytes `length` + ...
self.remove_privilege(&data[4..], params, state)
} else {
Ok(())
Err(vm::Error::InternalContract("unsupported function"))
}
}
}
11 changes: 5 additions & 6 deletions core/src/executive/internal_contract/impls/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
bytes::Bytes,
parameters::staking::*,
state::{State, Substate},
vm::{self, ActionParams, Spec},
vm::{self, ActionParams, CallType, Spec},
};
use cfx_types::{Address, U256};
use std::str::FromStr;
Expand Down Expand Up @@ -95,11 +95,10 @@ impl InternalContractTrait for Staking {
_substate: &mut Substate,
) -> vm::Result<()>
{
if state.is_contract(&params.sender) {
return Err(vm::Error::InternalContract(
"contract accounts are not allowed to deposit or withdraw",
));
if params.call_type == CallType::StaticCall {
return Err(vm::Error::MutableCallInStaticContext);
}

let data = if let Some(ref d) = params.data {
d as &[u8]
} else {
Expand Down Expand Up @@ -134,7 +133,7 @@ impl InternalContractTrait for Staking {
// `duration_in_day`.
self.lock(&data[4..], params, state)
} else {
Ok(())
Err(vm::Error::InternalContract("unsupported function"))
}
}
}
6 changes: 3 additions & 3 deletions internal_contract/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ The contract address is `0x8060de9e1568e69811c4a398f92c3d10949dc891`.

The contract address is `0x8ad036480160591706c831f0da19d1a424e39469`.

+ `set_sponsor_for_gas(address contract, uint upper_bound)`: If someone wants to sponsor the gas fee for a contract with address `contract`, he/she (it should be a normal account) should call this function and in the meantime transfer some tokens to the address `0x8ad036480160591706c831f0da19d1a424e39469`. The parameter `upper_bound` is the upper bound of the gas fee the sponsor will pay for a single transaction. The number of transfered tokens should be at least 1000 times of the `upper_bound`. The sponsor could be replaced if the new sponsor transfers more tokens and sets a larger upper bound. The current sponsor can also call the function to transfer more tokens to sponsor the contract. The `upper_bound` can be changed to a smaller one if current sponsor balance is less than the `upper_bound`.
+ `set_sponsor_for_collateral(address contract_addr)`: If someone wants to sponsor the CFS (collateral for storage) for a contract with address `contract`, he/she (it should be a normal account) should call this function and in the meantime transfer some tokens to the address `0x8ad036480160591706c831f0da19d1a424e39469`. The sponsor could be replaced if the new sponsor transfers more tokens. The current sponsor can also call the function to transfer more tokens to sponsor the contract.
+ `set_sponsor_for_gas(address contract, uint upper_bound)`: If someone wants to sponsor the gas fee for a contract with address `contract`, he/she (it can be a contract account) should call this function and in the meantime transfer some tokens to the address `0x8ad036480160591706c831f0da19d1a424e39469`. The parameter `upper_bound` is the upper bound of the gas fee the sponsor will pay for a single transaction. The number of transfered tokens should be at least 1000 times of the `upper_bound`. The sponsor could be replaced if the new sponsor transfers more tokens and sets a larger upper bound. The current sponsor can also call the function to transfer more tokens to sponsor the contract. The `upper_bound` can be changed to a smaller one if current sponsor balance is less than the `upper_bound`.
+ `set_sponsor_for_collateral(address contract_addr)`: If someone wants to sponsor the CFS (collateral for storage) for a contract with address `contract`, he/she (it can be a contract account) should call this function and in the meantime transfer some tokens to the address `0x8ad036480160591706c831f0da19d1a424e39469`. The sponsor could be replaced if the new sponsor transfers more tokens. The current sponsor can also call the function to transfer more tokens to sponsor the contract.
+ `add_privilege(address[] memory)`: A contract can call this function to add some normal account address to the whitelist. It means that if the `sponsor_for_gas` is set, the contract will pay the gas fee for the accounts in the whitelist, and if the `sponsor_for_collateral` is set, the contract will pay the CFS (collateral for storage) for the accounts in the whitelist. A special address `0x0000000000000000000000000000000000000000` could be used if the contract wants to add all account to the whitelist.
+ `remove_privilege(address[] memory)`: A contract can call this function to remove some normal account address from the whitelist.

Expand All @@ -22,5 +22,5 @@ The contract address is `0x8ad036480160591706c831f0da19d1a424e39469`.
The contract address is `0x843c409373ffd5c0bec1dddb7bec830856757b65`.

+ `deposit(uint amount)`: The caller can call this function to deposit some tokens to Conflux Internal Staking Contract. The current annual interest rate is 4%.
+ `withdraw(uint amount)`: The caller can call this function to withdraw some tokens to Conflux Internal Staking Contract. It will trigger a interest settlement. The staking capital and staking interest will be transferred to the user's balance in time. Withdrawal fee will be designed in linearly gradient-type from 0-0.05%. The fee is 0.05% of one-day staking and 0 of staking more than one year. All the withdrawal fees will be burned. All the withdrawal applications will be processed on a first-come-first-served basis according to the sequence of staking orders.
+ `withdraw(uint amount)`: The caller can call this function to withdraw some tokens to Conflux Internal Staking Contract. It will trigger a interest settlement. The staking capital and staking interest will be transferred to the user's balance in time. All the withdrawal applications will be processed on a first-come-first-served basis according to the sequence of staking orders.
+ `lock(uint amount, uint duration)`: This function is related with Voting Rights in Conflux. Staking users can choose the voting amount and locking maturity by locking a certain amount of CFX in a certain maturity from staking.

0 comments on commit ec5d697

Please sign in to comment.