There is sample code in "Modular Contracts" that uses a mapping, but I cannot see where that values of each mapping index get assigned.
The mapping is defined as:
mapping(address => uint256) balances;
and it is passed into the library function "Balances":
library Balances {
function move(mapping(address => uint256) storage balances,
address from,
address to,
uint amount) internal {
require(balances[from] >= amount);
require(balances[to] + amount >= balances[to]);
balances[from] -= amount;
balances[to] += amount;
...
But I don't see where any value is actually initially added to balances in any part of the full code example.
The move function first checks if balances[from] >= amount. At the end of that function you see it adds and subtracts from the identified balances, but that code will never be reached, right? Since require(balances[from] >= amount); will always return false.
What am I missing?
It's just an example of Modular Contracts you can add any balance in your constructor like
constructor() public {
balances[yourAddress] = amount
}
Related
I am trying to record all the transaction details done by any address like so:
contract GetPayment {
struct Payment {
uint amount;
uint timestamp;
}
mapping(address => Payment) public mainMap;
function pay() public payable {
mainMap[msg.sender].amount = msg.value;
mainMap[msg.sender].timestamp = now;
}
}
The problem with this code, is that every time the msg.sender makes a new transaction, it overwrites the previous data.
How to save the data without overwriting the previous data?
Maybe you want to use a mapping to a dynamic array of Payments and push a new payment each time it is made?
mapping(address => Payment[]) public mainMap;
function pay() public payable {
Payment[] storage payment = mainMap[msg.sender];
payment.push(Payment({amount: msg.value, timestamp: block.timestamp}));
mainMap[msg.sender] = payment;
}
That is if you want it to be accessed in the contract.
Otherwise, if you want to utilize it in the front-end, you can use an event with an inerrable element of the address to parse it.
I'm trying to add liquidity to my smart contract on Uniswap, however whenever I try to add liquidity, I can approve the transaction, but hitting apply does nothing. The Javascript console shows an error saying: not able to predict gas gee. There's also a problem with TransferFrom.
function transfer(address to, uint value) public returns(bool) {
require(balanceOf(msg.sender) >= value, 'balance too low');
//burn&tax
burn(msg.sender,burnTaxFee(value));
sendDev(msg.sender,devTaxFee(value));
balances[to] += value; //send the value - burnt tokens to reciever
balances[msg.sender] -= value ; //subtract value sent from sender.
emit Transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) public returns(bool) {
require(balanceOf(from) >= value, 'balance too low');
require(allowance[from][msg.sender] >= value, 'allowance too low');
//burn&tax
burn(msg.sender,burnTaxFee(value));
sendDev(msg.sender,devTaxFee(value));
balances[to] += value; //send the value - burnt tokens to reciever
balances[from] -= value; //subtract value sent from sender.
emit Transfer(from, to, value);
return true;
}
I'm thinking it might have to do with my smart contract? for each transfer, I also do 2 separate transfers that go into two separate wallets. Do multiple transfers triggered by the normal transfer function cause problems with uniswap?
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"code":-32603,"message":"execution reverted: TransferHelper: TRANSFER_FROM_FAILED","data":{"originalError":{"code":3,"data":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000245472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c454400000000000000000000000000000000000000000000000000000000","message":"execution reverted: TransferHelper: TRANSFER_FROM_FAILED"}}}, method="estimateGas", transaction={"from":"0xA6486944b1119CDAB743694873e28ad8eF3f89e2","to":"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D","value":{"type":"BigNumber","hex":"0x1717b72f0a4000"},"data":"0xf305d71900000000000000000000000054620e1c1c39d689fc73214bb1de16f743214dce0000000000000000000000000000000000000000000113d788ba2b887b6c80000000000000000000000000000000000000000000000113d788ba2b887b6c8000000000000000000000000000000000000000000000000000001717b72f0a4000000000000000000000000000a6486944b1119cdab743694873e28ad8ef3f89e20000000000000000000000000000000000000000000000000000000060c1817e","accessList":null}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.2.0)
Another idea I had was that I'm not using the SafeMath library, would non-safemath equations cause issues with Uniswap?
I'm currently trying to develop a simple smart contract
Being relatively new to this, can multiple pairs of users interact with the contract at the same time and benefit from the escrow (will it instantiate a new version for every pair) ?
It's essentially an escrow contract that will hold the funds from a transaction until both the buyer and the seller have accepted the release. Additionally, if the either one of them does not accept the funds will be withheld by the smart contract for a duration of 30 days.
Also, how can I add the address that initially deployed the smart and transfer 3% of the total deposit to that address if the transaction was successful ?
This is what I have tried for now:
pragma solidity 0.7.0;
contract NewEscrow {
enum State {AWAITING_FUNDS,AWAITING_CLAIM,CLAIM,COMPLETE}
State public currentState;
address payable public buyer;
address payable public seller;
address payable public owner;
uint256 public agreementDay;
mapping (address => uint256) deposits;
// checks if msg.sender is equal to buyer
modifier onlyBuyer (){
require(msg.sender == buyer);
_;
}
// checks if msg.sender is equal to seller
modifier onlySeller(){
require(msg.sender == seller);
_;
}
constructor (){
owner = msg.sender;
}
function setVariables (address payable _buyer, address payable _seller, uint256 _agreementDay) public {
buyer = _buyer;
seller = _seller;
agreementDay = _agreementDay + 30 days;
currentState = State.AWAITING_FUNDS;
}
function deposit() public onlyBuyer payable {
require(currentState == State.AWAITING_FUNDS);
uint256 amount = msg.value;
deposits[seller] = deposits[seller] + amount;
currentState = State.AWAITING_CLAIM;
}
function claim () public onlySeller {
require(currentState == State.AWAITING_CLAIM);
currentState = State.CLAIM;
}
function confirm () public onlyBuyer {
uint256 payment = deposits[seller];
deposits[seller] = 0;
seller.transfer(payment);
currentState = State.COMPLETE;
}
function cancelPayement () public onlySeller {
uint256 payment = deposits[seller];
deposits[seller] = 0;
buyer.transfer(payment);
currentState = State.COMPLETE;
}
function release() public{
// funds cannot be retrieved before release day
require (agreementDay < block.timestamp);
uint256 payment = deposits[seller];
deposits[seller] = 0;
buyer.transfer(payment);
revert('funds returned');
}
}
can multiple pairs of users interact with the contract at the same time and benefit from the escrow
Currently not. Only the first pair of users would be able to use it, as currently buyer and seller variables can only hold one value each.
If you want to scale for multiple pairs, you need to make an array of structs representing the buyer and seller connection. From the top of my head, it would look like:
struct Pair {
address buyer;
address seller;
}
Pair[] pairs;
Or another approach, where a common index of the arrays shows that the buyer and seller are connected.
address[] buyers;
address[] sellers;
This scaling would also mean expanding most of the current logic to validate whether the input buyer and seller are connected.
if the either one of them does not accept the funds will be withheld by the smart contract for a duration of 30 days
You'll need to create a new function that checks whether the deposit has been withdrawn and whether it's (deposit date + 30 days) and some validation who can actually withdraw this money.
address constant contractOwner = '0x123'
function withdrawOwner() external {
require(msg.sender == contractOwner); // validate who can withdraw
require(agreementDay + 30 days <= block.timestamp); // check if 30 days has passed since the deposit date
require(deposits[seller] > 0); // check that it hasn't been withdrawn
uint256 amount = deposits[seller]; // make sure the contract is not vulnerable to reentrancy
deposits[seller] = 0;
payable(contractOwner).transfer(amount); // withdraw the money
}
how can I add the address that initially deployed the smart and transfer 3% of the total deposit
Let's expand the 2nd point and use the contractOwner. You'll need to update the deposit function:
function deposit() public onlyBuyer payable {
require(currentState == State.AWAITING_FUNDS);
uint256 amount = msg.value;
// these lines calculate the fee, update the amount and send the fee to the contract owner
// make sure you're not vulnerable to overflow
uint256 fee = (amount / 100) * 3;
payable(contractOwner).transfer(fee); // transfer 3% to the contract owner
amount -= fee; // substract the fee from the amount that is going to be saved
deposits[seller] = deposits[seller] + amount;
currentState = State.AWAITING_CLAIM;
}
Make sure you're not vulnerable to integer overflow. Imagine a scenario:
Buyer deposits 1 wei
Fee is calculated as 3 wei
The contract has enough ETH so it sends the 3 wei to the owner
But the 3 wei is substracted from the 1 in amount so that results in 2^256 - 3 instead of -2
Solidity 0.8+ reverts the transaction automatically if underflow/overflow would happen. If you're using older version of Solidity, you can use for example OpenZeppelin's SafeMath library.
I'm writing a LibraryPortal Smart Contract in which multiple users can rent their books to each other. So, in this contract the msg.value contain the total amount which is a combination of the Security Deposit & the Renting Rate.
What I have to do is transfer the Renting amount to the owner of the book instantly & store the remaining amount in the contract i.e., the Security Deposit.
If the Renter will not return the book with in the time specified then the security amount will be transfered to the Owner of the book, otherwise get returned to the Renter.
Here is my snippet:
function borrowBook(string _bName) payable returns (string){
if(msg.sender != books[_bName].owner){
if(books[_bName].available == true){
if(getBalance()>=(books[_bName].amtSecurity + books[_bName].rate) ){
books[_bName].borrower = msg.sender;
books[_bName].available = false;
books[_bName].owner.transfer(msg.value - books[_bName].amtSecurity);
// Code missing
// For storing
// ETH into the Contact
return "Borrowed Succesful";
}else{
return "Insufficient Fund";
}
}else{
return "Currently this Book is Not Available!";
}
}else{
return "You cannot Borrow your own Book";
}
}
You can achieve the result from something called as Escrow contract.
Following is the implementation of Escrow contract by open-zeppelin:
contract Escrow is Secondary {
using SafeMath for uint256;
event Deposited(address indexed payee, uint256 weiAmount);
event Withdrawn(address indexed payee, uint256 weiAmount);
mapping(address => uint256) private _deposits;
function depositsOf(address payee) public view returns (uint256) {
return _deposits[payee];
}
/**
* #dev Stores the sent amount as credit to be withdrawn.
* #param payee The destination address of the funds.
*/
function deposit(address payee) public onlyPrimary payable {
uint256 amount = msg.value;
_deposits[payee] = _deposits[payee].add(amount);
emit Deposited(payee, amount);
}
/**
* #dev Withdraw accumulated balance for a payee.
* #param payee The address whose funds will be withdrawn and transferred to.
*/
function withdraw(address payee) public onlyPrimary {
uint256 payment = _deposits[payee];
_deposits[payee] = 0;
payee.transfer(payment);
emit Withdrawn(payee, payment);
}
}
You can just instantiate the contract in your contract and forward the funds to the contract.
For full implementation of similar functionality have a look at the refundable crowdsale contract
Thank you guys for answers but, later I came to know that the VALUE sent along with the transaction to the contract is stored in the Contract itself, & you can access that by using the address(this).balance which will always gives you the Balance available in that instance of the contract. Due to this you don't require any variable or other stuff to store ETHER in your contract.
New to solidity and geth for my traineeship, I started deploying contrcts using the solidity online IDE and the geth dev mode. My problem is I tried a few different ways to do it but nothing seems to really work.
Code:
contract Transaction {
address public owner;
mapping (address => uint) public balances;
function Transaction () {
owner = msg.sender;
}
function validateTransaction (address receiver, uint amount) constant returns (bool) {
if (balances[owner] < amount || owner == receiver || amount == 0)
return (false);
balances[owner] -= msg.value;
return (true);
}
function transact (address receiver, uint amount) {
if (!validateTransaction(receiver, amount))
return ;
balances[receiver] += msg.value;
}
function remove () {
if (msg.sender == owner)
selfdestruct(owner);
}
}
I also tried this contract of a solidity tutorial but it also don't work as I expected:
contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;
// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);
// This is the constructor whose code is
// run only when the contract is created.
function Coin() {
minter = msg.sender;
}
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}
I am just trying to make a smart contract that can make transactions between the sender and a receiver but the accounts balances don't move. Are that functions only abstract to learn how solidity works or can this really make the balances change ? Thanks for your answers :)
After have searched and work deeper on solidity I found that, indeed, this contract makes abstract transactions into HIS data. So the ether aren't truely sent and the balance variable is local to this contract.