I am building an NFT contract (ERC-721) on the Ethereum blockchain, I need to set up a fixed or percentage fee on each transfer/selling of NFT.
Please guide
In ERC721, there are 3 methods that provide NFT transfer:
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
Simply, what you would want to do is handle fees in the above methods. The most simplistic approach would be to collect the fee from caller, since all 3 methods are payable.
uint256 fee = 0.1 ether;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable{
require(msg.value >= fee, "sent ether is lower than fee")
// your erc721 implementation
}
Related
I want to ask if my contract is wrong or faulty since I created a simple swap contract with the pancakeswap router on testnet and the transaction has been succeed but the result token from the swapping is not transferred to the target address.
Below is the transaction URL from BSCScan testnet:
https://testnet.bscscan.com/tx/0xdaff70143fff6f1be08d20c31ebbfdb8117d067f9311fa130c189722f499ef09
This is the pancakeswap from the testnet:
https://pancake.kiemtienonline360.com/#/swap
This is the contract that I used to to the swap to the router:
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
interface IPancakeswap {
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function WETH() external pure returns (address);
}
interface IERC20 {
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function approve(address sender, uint256 amount) external returns (bool);
}
contract SwapProject {
IPancakeswap pancake;
constructor() {
pancake = IPancakeswap(0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3);
}
function WETH() external view returns(address){
address wbnb = pancake.WETH();
return wbnb;
}
function swapExactTokensForETH(
address token,
uint amountIn,
uint amountOutMin,
uint deadline
) external {
IERC20(token).transferFrom(msg.sender, address(this), amountIn);
address[] memory path = new address[](2);
path[0] = token;
path[1] = pancake.WETH();
uint deadlinePro = (deadline * 1 minutes) + block.timestamp;
IERC20(token).approve(address(pancake), amountIn);
pancake.swapExactTokensForETH(
amountIn,
amountOutMin,
path,
msg.sender,
deadlinePro
);
}
}
I want an address to send ETH to the smart contract in the RSVP function.
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract MeetingCreation {
struct Meeting {
address meeting_creator;
uint256 meetingID;
string name;
string description;
uint256 start_date;
uint256 end_date;
uint256 max_tickets;
uint256 ticket_price;
uint256 current_tickets_sold;
address[] attendees;
}
function sendETHtoContract(uint256 j) public payable {
}
function RSVP (uint256 MEETINGID) public payable {
//get the Meeting ID
Meeting storage m = meetings[MEETINGID];
require(m.current_tickets_sold < m.max_tickets,
"No more tickets available"
);
require(msg.sender.balance >= m.ticket_price,
"Not enough funds"
);
console.log("funds before paying", msg.sender.balance);
console.log("funds in smart contract before paying", address(this).balance);
//Attempt #1 To send ETH to contract
sendETHtoContract(m.ticket_price);
//Attempt #2 To send ETH to contract
(bool success, ) = address(this).call{value: m.ticket_price}("");
//Attempt #3 to send ETH to contract
payable(address(this).transfer(msg.value));
console.log("funds AFTEr paying", msg.sender.balance);
console.log("funds in smart contract AFTER paying", address(this).balance);
address[] storage adr;
adr = m.attendees;
adr.push(msg.sender);
m.current_tickets_sold += 1;
}
Both sendETHtoContract and (bool, success) result in not sending any ETH when I tried 3 different addresses.
funds before paying 9999949127225257315696
funds in smart contract before paying 0
funds AFTEr paying 9999949127225257315696
funds in smart contract AFTER paying 0
funds before paying 9999955000801324655336
funds in smart contract before paying 0
funds AFTEr paying 9999955000801324655336
funds in smart contract AFTER paying 0
When I tried using the transfer function, this is the error I get when the contract tries to compile:
"send" and "transfer" are only available for objects of type "address payable", not "address".
I assume that you can delete your attempt for the simple reason that when you add payable modifier, it handle the transfer about ETH from address to smart contract and viceversa.
Said this, I think that you're not enhancing msg.value field. If you using remix IDE, before call RSVP function go into DEPLOY & RUN TRANSACTIONS section and put into VALUE textbox a value that you want sending to smart contract and then you can call RSVP function.
I adjust your smart contract delete your attempts. Try it:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract MeetingCreation {
struct Meeting {
address meeting_creator;
uint256 meetingID;
string name;
string description;
uint256 start_date;
uint256 end_date;
uint256 max_tickets;
uint256 ticket_price;
uint256 current_tickets_sold;
address[] attendees;
}
mapping(uint => Meeting) meetings;
function RSVP (uint256 MEETINGID) public payable {
//get the Meeting ID
Meeting storage m = meetings[MEETINGID];
require(m.current_tickets_sold < m.max_tickets,
"No more tickets available"
);
require(msg.sender.balance >= m.ticket_price,
"Not enough funds"
);
address[] storage adr;
adr = m.attendees;
adr.push(msg.sender);
m.current_tickets_sold += 1;
}
// NOTE: Get smart contract balance
function getSmartContractBalance() external view returns(uint) {
return address(this).balance;
}
}
I want to call the function of contract A in my contract B. I call the balanceOf function to display the balance normally, but when I call the transfer function, it does display
Note: The called function should be payable if you send value and the value you send should be less than your current balance. I can't even add payable. Can anyone help?
my A contract
function transfer(address _to, uint256 _value)
external
payable
returns (bool success)
{function transfer(address _to, uint256 _value)
external
payable
returns (bool success)
{
require(balancesOf[msg.sender] >= _value);
require(_to != address(0));
require(balancesOf[_to] + _value > balancesOf[_to]);
balancesOf[msg.sender] -= _value;
balancesOf[_to] += _value;
return true;
}
my B contract
interface X {
function balanceOf(address _owner) external view returns (uint256 balance);
function transfer(address _to, uint256 _value)external payable returns (bool success);
}
contract A {
X public token;
constructor(address payable _address){
token = X(_address);
}
function GetbalanceOf(address _owner) external view returns (uint balance) {
return token.balanceOf(_owner);
}
function buy(address xx) external {
token.transfer(xx,100);
}
}
It seems like your not using any msg.value inside the transfer function of contract A henceforth u don't need the function to be payable. Also it might be because there is already a transfer function built in for sending ether.
You should change your transfer name to something else because its conflicting with the already built in transfer function of solidity.
i want make test and get data about DAI asset with solidity . i used this interfaces.
interface IProtocolDataProvider {
struct TokenData {
string symbol;
address tokenAddress;
}
function getAllReservesTokens() external view returns (TokenData[] memory);
function getAllATokens() external view returns (TokenData[] memory);
function getReserveConfigurationData(address asset) external view returns (uint256 decimals, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, bool isActive, bool isFrozen);
function getReserveData(address asset) external view returns (uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp);
function getUserReserveData(address asset, address user) external view returns (uint256 currentATokenBalance, uint256 currentStableDebt, uint256 currentVariableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 liquidityRate, uint40 stableRateLastUpdated, bool usageAsCollateralEnabled);
function getReserveTokensAddresses(address asset) external view returns (address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress);
}
and my contract is :
contract getData{
IProtocolDataProvider public AD;
constructor(address _ada) {
AD = IProtocolDataProvider(_ada);
}
function getD(address _asset) public view returns(uint){
(
uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp
) = AD.getReserveData(_asset);
return availableLiquidity;
}
}
i used both (MAIN AND KOVAN) address of Protocol Data Provider from AAVE source :
https://docs.aave.com/developers/deployed-contracts/deployed-contracts
and i test it with DAI address : 0x6B175474E89094C44Da98b954EedeAC495271d0F , and in remix i get this error : call to getData.getD errored: VM execution error.
Reverted 0x .
any help please
When I call transferUSDT i got a 'BEP20: transfer amount exceeds balance' but i know i got suffisent funds. I think i miss something in my smart contract.. Here the error on the bscscan:
https://testnet.bscscan.com/tx/0x3a253a8c32ed19bdbed66499ec2f888eae5114d44eba7c2f28a185258e91641f
pragma solidity >=0.7.0 <0.9.0;
abstract contract IUSDT{
function approve(address _spender, uint _value) virtual external returns (bool);
function transferFrom(address _from, address _to, uint _value) virtual public;
function transfer(address recipient, uint256 amount) virtual external returns (bool);
}
contract usdtTransfer{
IUSDT TetherContract;
function transferUSDT(uint256 amount) public {
TetherContract.transfer(address(this),amount);
}
constructor(address _tetherAddress){
TetherContract=IUSDT(_tetherAddress);
}
}
TetherContract.transfer(address(this),amount);
This snippet is trying to transfer amount (2nd argument) of tokens to the address(this) (1st argument) address - which is the address of the usdtTransfer contract.
And since it's executed from the usdtTransfer contract, it's trying to send the tokens from the very same usdtTransfer address.
If your goal is to send the tokens from the user to your contract, the user needs to first execute the approve() function on the token contract (from their address, passing your address as the spender param).