I am trying to make a smart contract to achieve the following automatically. But I stuck in the implementation. How can I run the (2) Tx without having B to sign the Tx, ie: I want it to run automatically once (1) is activated and condition (2) is ready.
Pseudocode(one):
A send 50 to B (1)
if (B > 50) (2)
B send 10 to C (3)
The code above involves multiple owners, ie. A, B and C. Firstly, A actives the contract by running/signing Tx (1). Then the contract checks condition (2). Now but how can run(3) automatically without having to force B to sign?
Ultimately, is the contract able to sign (or proxy sign) on behave of B?
edit
What about below in any chaincode? Can it run automatically, ie without D has to sign using D's private key in (3)?
Pseudocode(two):
A send 50 to B (1)
if (something is true, say Z > 50) (2)
D send 10 to F (3)
Ultimately, is the contract able to sign (or proxy sign) on behave of B?
No.
A starts the transactions by sending necessary funds to the contract, and then the contract disperses funds according to the rules. So, A -> contract, contract -> B and possibly, contract -> C.
Although it's outside the question raised, it will possibly help you avoid refactoring later to observe the best practice of separating the two sends if B and/or C are untrusted contracts. You would just do the accounting in the deposit step, and then use a withdrawal pattern as B & C claim their entitlements (separate transactions).
Hope it helps.
Updated:
Here's a rough outline that might give you some ideas. I wasn't sure if the > 50 was all-time total or a single payment > 50. It's a contrived example that expects you to pass in two valid addresses for B & C so the contract knows their addresses.
You can send amounts from any address (A) and the contract will keep track of owedToB and owedToC.
You should be able to send a transaction to withdraw() from B or C to claim the balance owed.
It's a little time-consuming to set everything up for a full test so just presenting "as is".
pragma solidity ^0.4.6;
contract Royalty {
address public B;
address public C;
uint public owedToB;
uint public owedToC;
event LogPaymentReceived(address sender, uint amount);
event LogPaid(address recipient, uint amount);
// pass in two addresses, B & C for this simple constructor
function Royalty(address addressB, address addressC) {
B = addressB;
C = addressC;
}
function pay()
public
payable
returns(bool success)
{
owedToB += msg.value;
// You can do B.balance > 50 but beware how it drops below 50 after withdrawal
// A little more involved, but you can have totalReceipts AND totalPayments so owedToB is totalReceipts - totalPayments
// It all depends on the business terms you're trying to enforce.
if(msg.value > 50) {
owedToC += 10;
owedToB -= 10;
}
LogPaymentReceived(msg.sender, msg.value);
return true;
}
function withdraw()
public
returns(uint amountSent)
{
if(msg.sender != B && msg.sender != C) throw; // only B & C can withdraw
uint amount;
if(msg.sender == B) {
amount = owedToB;
owedToB = 0;
if(!B.send(amount)) throw;
LogPaid(B,amount);
return amount;
}
if(msg.sender == C) {
amount = owedToC;
owedToC = 0;
if(!C.send(amount)) throw;
LogPaid(C,amount);
return amount;
}
// we shouldn't make it this far
throw;
}
}
Related
I want to pay two transactions within one function.
The msg.sender should pay a fee to the contract first. The rest which is still in msg.value should be transferred to the seller. I always get an error. To clarify i tested both transactions by their own and it worked and i have implemented a receive() function that the contract can receive the funds. Here is the code:
function sendMoney() public payable {
address payable seller = payable(address(this));
address payable sellerino = payable(0x910DCE3971F71Ee82785FF86B47CaB938eBB9E68);
sellerino.transfer(10);
seller.transfer(msg.value);
}
Here the error:
https://blockscout.mantis.hexapod.network/tx/0x343817da970dce47c74094f4766f9c7f21ee258ea848e117893afa53c4768dac/internal-transactions
Additional Code:
function buyTicketFromAttendee(uint256 _ticketId)
external
payable
{
require(eventticket[_ticketId - 1].availableForResell = true,"ticket not for sale");
uint256 _priceToPay = eventticket[_ticketId - 1].ticketPrice;
//address owner = ownerOf(_ticketId);
require((msg.value >= _priceToPay + transferFee),"not enough money");
address seller = eventticket[_ticketId - 1].seller;
address owner = eventticket[_ticketId - 1].owner;
payable(owner).transfer(transferFee);
payable(seller).transfer(msg.value - transferFee);
_transfer(address(this), msg.sender, _ticketId);
//payable(seller).transfer(_priceToPay);
eventticket[_ticketId - 1].availableForResell = false;
}
Your snippet is trying to send more funds than the contract has - which causes the whole transaction to revert.
The contract has 0 MANTIS before the transaction invoking sendMoney().
The transaction sent along 0.1 MANTIS ( == 100000000000000000 wei), which is reflected in the msg.value global variable.
The first transfer() sends 10 wei, so the left available balance is now 99999999999999990 wei (10 less than 0.1 MANTIS). But the second transfer() is trying to send 100000000000000000 (the msg.value), which is 10 wei more than the contract has available at the moment.
Solution: Lower the second transfer by the already sent amount.
sellerino.transfer(10);
seller.transfer(msg.value - 10);
I'm creating a solidity contract for an NFT and in my mint function I'm not sure if a call to totalSupply() vs using a token counter and incrementing it is better practice. Does either variation cost more gas? Is one the more standard practice? I've seen examples of both being used.
Variation 1:
contract MyNFT is ERC721Enumerable, PaymentSplitter, Ownable {
using Counters for Counters.Counter;
Counters.Counter private currentTokenId;
...
function mint(uint256 _count)
public payable
{
uint256 tokenId = currentTokenId.current();
require(tokenId < MAX_SUPPLY, "Max supply reached");
for(uint i = 0; i < _count; ++i){
currentTokenId.increment();
uint256 newItemId = currentTokenId.current();
_safeMint(msg.sender, newItemId);
}
}
}
Variation 2:
function mint(uint256 _count)
public payable
{
uint supply = totalSupply();
require( supply + _count <= MAX_SUPPLY, "Exceeds max supply." );
for(uint i = 0; i < _count; ++i){
_safeMint(msg.sender, supply + i);
}
}
Both versions seem to work. I just want to be sure I'm using the most efficient / secure. Thanks for any advice!
First off all, you need to show us the underlying implementations. However, I can speculate that these are unmodified openzeppelin implementations for ERC721Enumerable and Counters.
For your case only, using Counter seems a little bit pointless to me.
It increases your deployment costs(just a little bit) because of redundant code coming from Counter library
You already know the length of your tokens array, why keep it twice? Counters is created for situations where you don't know the number of elements, like a mapping.
I am not guaranteeing correctness of the following analysis
Calling totalSupply (looking from opcode point of view) will:
jump to totalsupply (8 gas)
sload tokens.slot (200) gas
However, while using Counter, you sstore (>= 5000 gas) each time you decrement and sload (200 gas) each time you read.
As long as i am not mistaken about Counter using storage, and therefore sstore and sload opcodes, second variant will use much less gas.
I have recently been delving into the code of a few contracts and have been commenting them myself to try and understand how they work as the entire field seems ironically black-box from a development perspective with most code copy and pasted from other contracts with 0 comments explaining what functions do.
As such I have seen a recurring function across multiple projects which I am struggling to get my head around. Namely shouldswapback() and swapback().
shouldSwapBack():
function shouldSwapBack() internal view returns (bool) {
return msg.sender != pair
&& !inSwap
&& swapEnabled
&& _balances[address(this)] >= swapThreshold;
}
My understanding of above is to return true only when the caller of the function is not the LP address, swapping is allowed and we are not in a swap currently and the balance of the contract is >= the predefined swap threshold.
2 questions regarding this:
1. In what context/circumstance is the msg.sender the LP contract?
2. Why is it important to only swap if the contract balance is greater than a certain percentage? What would be the effect if this was 0?
The actual swap function is longer:
function swapBack() internal swapping {
uint256 contractTokenBalance = balanceOf(address(this));
/* (contract balance * 3)/15/2 */
uint256 amountToLiquify = contractTokenBalance.mul(liquidityFee).div(totalFee).div(2);
uint256 amountToSwap = contractTokenBalance.sub(amountToLiquify);
/* set the address path for the BNB and Token addresses */
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = WBNB;
/* note before balance of contract */
uint256 balanceBefore = address(this).balance;
/*swap tokens using PCS */
router.swapExactTokensForETHSupportingFeeOnTransferTokens(
amountToSwap, /*The amount of input tokens to send. */
0, /*The minimum amount of output tokens that must be received for the transaction not to revert. */
path, /*An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity. */
address(this), /*Recipient of the BNB. */
block.timestamp /*Unix timestamp after which the transaction will revert. (Think set to one block?)*/
);
uint256 amountBNB = address(this).balance.sub(balanceBefore); /* get amount swapped by checking new contract balance vs beforeswap */
uint256 totalBNBFee = totalFee.sub(liquidityFee.div(2));
uint256 amountBNBLiquidity = amountBNB.mul(liquidityFee).div(totalBNBFee).div(2);
uint256 amountBNBMarketing = amountBNB.mul(marketingFee).div(totalBNBFee);
/* send marketing fee to marketing wallet */
(bool MarketingSuccess, /* bytes memory data */) = payable(marketingFeeReceiver).call{value: amountBNBMarketing, gas: 30000}("");
require(MarketingSuccess, "receiver rejected ETH transfer");
/* if we meet the liquidity threshold add to marketwallet */
if(amountToLiquify > 0){
router.addLiquidityETH{value: amountBNBLiquidity}(
address(this),
amountToLiquify,
0,
0,
marketingFeeReceiver,
block.timestamp
);
emit AutoLiquify(amountBNBLiquidity, amountToLiquify);
}
}
My understanding for this is that the contract tokens are swapped to BNB and then the fees are calculated and sent to the appropriate wallet. However with this I don't understand:
1.Why are the tokens going the contract and not the LP?
2.If all the tokens are swapped to ETH do none get swapped back?
3.What is the significance of adding to the LP, why would this be necessary? (if this wasn't done what would the affect be on the token? I have seen projects fail in the past because they didn't buyback liquidity but I'm struggling to understand what it would do apart from ease volatility?)
I understand that this a lengthy question and my issue seems to be less from a code perspective and more from a key concept one but if anyone could help me it would be great. I have looked online for courses but none seem to really delve into dex interactions, a lot just seem very basic token/NFT creation I haven't been able to find one tutorial on making a contract that has a working tax implementation so instead I've just been cross referencing a bunch of different contracts.
If anyone can point me in the right direction for a course or even better a tutor that would be great.
Thanks.
I'd like to mint these amount of tokens:
200 super
300 rare
500 common
But the mint process needs to be random, you can get a (super, rare, or common) but at the end of the process, it should be minted the same amount of 200 super, 300 rare, and 500 common.
The following code does the random but the final amount of tokens will be different from the beginning:
function safeMint(address to) public onlyOwner {
require(_tokenIdCounter.current() < totalSupply(), "There's no token to mint.");
require(mintCnt[msg.sender] < maxMintCntPerAddress, "One address can mint 1 tickets.");
if(mintPrice > 0) {
require(mintPrice == msg.value, "Mint price is not correct.");
address payable _to = payable(serviceAddress);
_to.transfer(mintPrice);
}
uint randomNumber = random(expectedTokenSupply - _tokenIdCounter.current());
for (uint256 i = 0; i < _tokenMetadata.length; i++) {
if(_tokenMetadata[i].amount <= randomNumber) {
_safeMint(to, _tokenIdCounter.current());
_setTokenURI(_tokenIdCounter.current(), _tokenMetadata[i].uri);
_tokenIdCounter.increment();
break;
}
}
}
function random(uint maxValue) internal returns (uint) {
return uint(keccak256(abi.encodePacked(block.timestamp, msg.sender, _tokenIdCounter.current()))) % maxValue;
}
First don't use block.timestamp or any block or blockchain data as a source of randomness, because it will cause the "randomness" be predictable or possible to be manipulated by minners, try with chainlink as a source of randomness, they have a good examples in their docs, if you want to have a fixed supply of each type of tokens you can have 3 variables to know how much of each one have been minted, and when you got the random number and all that you need you just need to apply some math, in this case you want the tokens to be 20% of super, 30% of rare and 50% of common, you only have to do the math you need to decide wich one will be minted, and in case of that type has already reach is max supply what will happend?
I have a pretty boilerplate test token that I'm going to use to support a DApp project. Key functions I have questions regarding are as follows:
constructor() {
name = "Test Token";
symbol = "TTKN";
decimals = 18;
_totalSupply = 1000000000000000000000000000000;
//WITHOUT DECIMALS = 1,000,000,000,000; should be 1 trillion
balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
function totalSupply() public override view returns (uint256) {
return _totalSupply - balances[address(0)];
}
First, a quick question about decimals and supply: did I set this up correctly to create 1 trillion of the TTKN token? And do I really need so many decimal places?
Second, what exactly is address(0)? My understanding of the constructor is that address(0) first transfers all the tokens to msg.sender, which is me, the person who deploys this contract.
And finally, what are the best practices for initially distributing the tokens? What I want is basically as follows:
a) Myself and a few other devs each get 1% of the initial supply
b) Our DApp, a separate smart contract, will get 50% of the initial supply, and will use this to reward users for interacting with our website/project
c) To accomplish a) and b), me, the contract deployer, should manually transfer these tokens as planned?
d) The rest of the coins... available to go on an exchange somehow (maybe out of scope of question)
So now that I've deployed this test token on remix and am getting a feel for how to transfer around the tokens, I want to understand the above points in relation to our project. Is my plan generally acceptable and feasible, and is it the case that as the initial owner I'm just making a bunch of transfer calls on the ETH mainnet eventually when I deploy?
did I set this up correctly to create 1 trillion of the TTKN token?
This is one of the correct ways. More readable would be also:
_totalSupply = 1000000000000 * 1e18;
or
// 10 to the power of
_totalSupply = 1000000000000 * (10 ** decimals);
^^ mind that this snippet performs a storage read (of the decimals variable) so it's more expensive gas-wise
a well as
_totalSupply = 1000000000000 ether;
^^ using the ether unit, an alias for * 1e18
what exactly is address(0)
If it's in the first param of the Transfer event, it means the tokens are minted. If it's in the second param, it means a burn of the tokens.
A token contract which creates new tokens SHOULD trigger a Transfer event with the _from address set to 0x0 when tokens are created.
Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transfer-1
initially distributing the tokens
You can perform the distribution in the constructor. For the sake of simplicity, my example shows the "exchange" as a regular address managed by your team that will send the tokens to the exchange manually. But it's possible to list a token on a DEX automatically as well.
_totalSupply = 1000000000000 * 1e18;
address[3] memory devs = [address(0x123), address(0x456), address(0x789)];
address dapp = address(0xabc);
address exchange = address(0xdef);
// helper variable to calculate the remaining balance for the exchange
uint256 totalSupplyRemaining = _totalSupply;
// 1% for each of the devs
uint256 devBalance = _totalSupply / 100;
for (uint i = 0; i < 3; i++) {
balances[devs[i]] = devBalance;
emit Transfer(address(0x0), devs[i], devBalance);
totalSupplyRemaining -= devBalance;
}
// 50% for the DApp
uint256 dappBalance = _totalSupply / 2;
balances[dapp] = dappBalance;
emit Transfer(address(0x0), dapp, dappBalance);
totalSupplyRemaining -= dappBalance;
// the rest for the exchange
balances[exchange] = totalSupplyRemaining;
emit Transfer(address(0x0), exchange, totalSupplyRemaining);