I am creating an ERC20 token. Can I make initial supply 0? If yes than how will increase supply later on?
I just wanna know that can I make initial supply 0 while deploying an ERC20 token?
Yes, you can create an ERC20 token with 0 initial supply by not minting any tokens in the constructor.
Example code with the OpenZeppelin ERC20 implementation. Mind that this code is simplified and not suitable for production as it allows minting new tokens by anyone.
pragma solidity ^0.8;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
// no token minting in constructor => initial supply is 0
}
// you can call this function later to increase the total supply
function mint(uint256 amount) external {
_mint(msg.sender, amount);
}
}
Related
The token is ERC721 by OpenZeppelin
I'm trying to add USDC payments to my Smart Contract, but I'm having problems.
This is my function to accept token.. but transfer its called by Smart Contract. Dont work...
function AcceptPayment(uint32 amount) public {
tokenUSDC.transfer(address(this), amount * priceCapsule);
bulkMint(_msgSender(), amount);
}
Allowance and approve its working fine, testing with Remix.
New try.. but get: Execution reverted on Remix
function AcceptPayment(uint32 amount) public {
bool success = tokenUSDC.transferFrom(msg.sender, address(this), amount * priceCapsule);
require(success, "Could not transfer token. Missing approval?");
bulkMint(_msgSender(), amount);
}
I can't find a solution to make the transfer from the Smart Contract itself.
The user needs to approve() your contract address to pull their tokens. This action needs to be called directly from the user address (on the token contract).
Then you can transferFrom() their address to yours.
function AcceptPayment(uint32 amount) public {
bool success = tokenUSDC.transferFrom(msg.sender, address(this), amount * priceCapsule);
require(success, "Could not transfer token. Missing approval?");
bulkMint(_msgSender(), amount);
}
I am currently using the Open Zapeline smart contract for my Dapp, I wanted to know if there is a way where users can claim my tokens (i.e transfer from owner wallet to current user) I know a method with hardcoding the private keys but is there any way wherein the Smart Contract I can set msg.Sender as Owner or Transfer tokens from Owner account to the user without any signatures?
You can use the internal function _transfer() (GitHub link) that only validates is the from param is the actual owner of the token. But it doesn't validate if the msg.sender is the token owner.
Note that this function has internal visibility, so it's only executable from inside of your contract.
pragma solidity ^0.8;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract MyCollection is ERC721, Ownable {
constructor() ERC721("MyCollection", "MyC") {
_mint(owner(), 1);
}
function claim() external {
require(ownerOf(1) == owner(), "Already claimed");
_transfer(owner(), msg.sender, 1);
}
}
While attempting to send tokens via a contract I run in to the error message: "SafeMath: subtraction overflow."
Initially I only used the transfer functionality. However, as I thought the msg.sender only has to send its tokens to the other user (via truffle console this is no issue). However, reading [this] I got the impression it is actually the contract address that becomes the msg.sender in the TokenContract. Therefore, (as only the accounts but not the contract itself) I thought that I have to send tokens to the contract first, subsequently approve that the contract is allowed to send tokens on behalf of the msg.sender and subsequently transfer the money. However, I keep having the SafeMath error.
The TokenContract (not the interface below) implements the The most simple version of my code is as follows:
contract ContractA {
function pay () public returns (bool) {
TokenContract tk = TokenContract("tokenContractAddress");
tk.transferFrom(msg.sender, address(this), 5);
tk.approve(address(this), 5);
tk.transfer("someAccount", 5);
return true;
}
}
interface TokenContract {
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
}
contract TokenContract is ERC20, ERC20Detailed {
constructor() ERC20Detailed("Token", "TKN", 18) public {
_mint(msg.sender, 1000);
}
}
Obviously I expect not the safeMath error to appear. As I transfer money and approve. I just expect the same behaviour as when using truffle console.
I assume that the address calling ContractA hasn't set an allowance for the contract.
Requirements:
* the caller must have allowance for sender's tokens of at least amount.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.3.0/contracts/token/ERC20/ERC20.sol
/**
* #dev See `IERC20.transferFrom`.
*
* Emits an `Approval` event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of `ERC20`;
*
* Requirements:
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `value`.
* - the caller must have allowance for `sender`'s tokens of at least
* `amount`.
*/
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
return true;
}
Caller of Contract A approves an allowance for the Token
Caller of Contract A calls pay function and which calls transferFrom to transfer from the user to the recipient within the previously set allowance.
If you are creating ERC20 tokens you may want to look at the OpenZeppelin Contracts implementation to see if this meets your needs. See the documentation for details: https://docs.openzeppelin.com/contracts/2.x/tokens#ERC20
If you are transferring a variety of ERC20 tokens you may want to consider using SafeERC20 wrapper to make these calls: https://docs.openzeppelin.com/contracts/2.x/api/token/erc20#SafeERC20
If you need an interface for ERC20 you may want to look at using IERC20: https://docs.openzeppelin.com/contracts/2.x/api/token/erc20#IERC20
Alternatively to ERC20 you could look at creating ERC777 tokens (no need to do approve and transferFrom in two separate transactions). See the documentation for details: https://docs.openzeppelin.com/contracts/2.x/tokens#ERC777
If you have questions on using OpenZeppelin you can ask in the Community Forum: https://forum.openzeppelin.com/
Disclosure: I am the Community Manager at OpenZeppelin
This is the interface that is required for a token to be an ERC20 token
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
I want to keep private the address of who owns my token. So I deleted the Transfer event and the Approval event. I also made the balanceOf function private.
Is there still some way for a public person to find out who owns one of my tokens? Also is there some way for a public person to know when a trade has taken place?
Is it private?
No
Is there still some way for a public person to find out who owns one of my tokens? Also is there some way for a public person to know when a trade has taken place?
The storage of the contract can be inspected, and the transaction data can be inspected. This data is necessarily public. The best you can do is make it harder for your median user to find this information (although the people who know what they're doing could dig it out and then publish it).
Is it an ERC20 token?
No
This is the interface that is required for a token to be an ERC20 token... I deleted the Transfer event and the Approval event. I also made the balanceOf function private.
Note that deleting those things makes it not an ERC20 token anymore. Those are required in the ERC20 spec.
What now?
Transactions that are private on a public blockchain is an ongoing area of research. If you really want to implement this, it will take diving into the current research in the space, getting familiar with things like ZK-SNARKS and alternatives.
Yes, one of the major features of Bitcoin and Ethereum are that they are public. When anyone uses your smart contract, all their actions are recorded, necessarily and by design, in the blockchain.
See this tx which called a smart contract method. Notice how I can see who sent what to whom, what function was called, and with what parameters.
Scenario
I am using the OWIN cookie authentication middleware to protected my site as follows
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
ExpireTimeSpan = new TimeSpan(0, 20, 0),
SlidingExpiration = true
});
}
On login, I use the resource owner password flow to call my token service and retrieve both an access and refresh token.
I then add the refresh token, access token and the time the access token expires to my claims and then call the following to to persist this information to my authentication cookie.
HttpContext
.GetOwinContext()
.Authentication
.SignIn(claimsIdentityWithTokenAndExpiresAtClaim);
Then before calling any service, I can retrieve the access token from my current claims and associate it with the service call.
Problem
Before calling any service, I should really check if the access token has expired and if so use the refresh token to get a new one. Once I have a new access token, I can call the service, however I then need to persist a new authentication cookie with the new access token, refresh token and expiry time.
Is there any nice way to do this transparently to the caller of the service?
Attempted solutions
1) Check before calling every service
[Authorize]
public async Task<ActionResult> CallService(ClaimsIdentity claimsIdentity)
{
var accessToken = GetAccessToken();
var service = new Service(accessToken).DoSomething();
}
private string GetAccessToken(ClaimsIdentity claimsIdentity) {
if (claimsIdentity.HasAccessTokenExpired())
{
// call sts, get new tokens, create new identity with tokens
var newClaimsIdentity = ...
HttpContext
.GetOwinContext()
.Authentication
.SignIn(newClaimsIdentity);
return newClaimsIdentity;
} else {
return claimsIdentity.AccessToken();
}
}
This would work, but it's not sustainable. Also I could not longer use dependency injection to inject my services as the service needs the access token at call time and not construction time.
2) Use some kind of service factory
Before create the service with its access token, it would perform the refresh if needed. The issue it that I'm not sure how I can get the factory to return both a service and also set the cookie within the implementation in a nice way.
3) Do it in a action filter instead.
The thinking is that the session cookie has a 20 minutes sliding expiry. On ever page request, I can check if the access token is more than halfway through it's expiry (ie. if the access token has an expiry of an hour, check to see if it has less than 30 minutes to expiry). If so, perform the refresh. The services can rely on the access token not being expired. Lets say you hit the page just before the 30 minutes expiry and stayed on the page for 30 minutes, the assumption is the session timeout (20 minutes idle) will kick in before you call the service and you wil be logged off.
4) Do nothing and catch the exception from calling a service with an expired token
I couldn't figure out a nice way to get a new token and retry the service call again without having to worry about side effects etc. Plus it would be nicer to check for expiration first, rather than wait for the time it takes the service to fail.
Neither of these solutions are particularly elegant. How are others handling this?
Update:
I spent some time looking in to various options on how to implement this efficiently at the server side with your current setup.
There are multiple ways (like Custom-Middleware, AuthenticationFilter, AuthorizationFilter or ActionFilter) to achieve this on the server side. But, looking at these options I would lean towards AuthroziationFilter. The reason are:
AuthroziationFilters gets executed after AuthenticationFilters. So, it is early in the pipe line that you can make a decision of whether to get a new token or not based on expiry time. Also, we can be sure that the user is authenticated.
The scenario we are dealing with is about access_token which is related to authorization than the authentication.
With filters we have the advantage of selectively using it with actions that are explicitly decorated with that filter unlike the custom middleware which gets executed with every request. This is useful as there will be cases where you do not want to get a refreshed token (since the current one is still valid as we are getting new token well before the expiration) when you are not calling any service.
Actionfilters are called little late in the pipeline also we do not have a case for after executing method in an action filter.
Here is a question from Stackoverflow that has some nice details on how to implement an AuthorizationFilter with dependency injection.
Coming to attaching the Authorization header to the service:
This happens inside your action method. By this time you are sure that the token is valid. So I would create an abstract base class that instantiates a HttpClient class and sets the authorization header. The service class implements that base class and uses the HttpClient to call the web service. This approach is clean as consumers of your setup do not have to know how and when you are getting and attaching the token to the outgoing request for web service. Also, you are getting and attaching the refreshed access_token only when you are calling the web service.
Here is some sample code (please note that I haven't fully tested this code, this is to give you an idea of how to implement):
public class MyAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
private const string AuthTokenKey = "Authorization";
public void OnAuthorization(AuthorizationContext filterContext)
{
var accessToken = string.Empty;
var bearerToken = filterContext.HttpContext.Request.Headers[AuthTokenKey];
if (!string.IsNullOrWhiteSpace(bearerToken) && bearerToken.Trim().Length > 7)
{
accessToken = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
}
if (string.IsNullOrWhiteSpace(accessToken))
{
// Handle unauthorized result Unauthorized!
filterContext.Result = new HttpUnauthorizedResult();
}
// call sts, get new token based on the expiration time. The grace time before which you want to
//get new token can be based on your requirement. assign it to accessToken
//Remove the existing token and re-add it
filterContext.HttpContext.Request.Headers.Remove(AuthTokenKey);
filterContext.HttpContext.Request.Headers[AuthTokenKey] = $"Bearer {accessToken}";
}
}
public abstract class ServiceBase
{
protected readonly HttpClient Client;
protected ServiceBase()
{
var accessToken = HttpContext.Current.Request.Headers["Authorization"];
Client = new HttpClient();
Client.DefaultRequestHeaders.Add("Authorization", accessToken);
}
}
public class Service : ServiceBase
{
public async Task<string> TestGet()
{
return await Client.GetStringAsync("www.google.com");
}
}
public class TestController : Controller
{
[Authorize]
public async Task<ActionResult> CallService()
{
var service = new Service();
var testData = await service.TestGet();
return Content(testData);
}
}
Please note that using the Client Credentials flow from OAuth 2.0 spec is the approach we need to take when calling an API. Also, the JavaScript solution feels more elegant for me. But, I am sure you have requirements that might be forcing you to do it the way you want. Please let me know if you have any questions are comments. Thank you.
Adding access token, refresh token and expires at to the claims and passing it to the following service may not be a good solution. Claims are more suited for identifying the user information/ authorization information. Also, the OpenId spec specifies that the access token should be sent as part of the authorization header only. We should deal with the problem of expired/ expiring tokens in a different way.
At the client, you can automate the process of getting a new access token well before its expiration using this great Javascript library oidc-client. Now you send this new and valid access token as part of your headers to the server and the server will pass it to the following APIs. As a precaution, you can use the same library to validate the expiration time of the token before sending it to the server. This is much cleaner and better solution in my opinion. There are options to silently update the token without the user noticing it. The library uses a an iframe under the hood to update the token. Here is a link for a video in which the author of the library Brock Allen explains the same concepts. The implementation of this functionality is very straightforward. Examples of how the library can be used is here. The JS call we are interested in would look like:
var settings = {
authority: 'http://localhost:5000/oidc',
client_id: 'js.tokenmanager',
redirect_uri: 'http://localhost:5000/user-manager-sample.html',
post_logout_redirect_uri: 'http://localhost:5000/user-manager-sample.html',
response_type: 'id_token token',
scope: 'openid email roles',
popup_redirect_uri:'http://localhost:5000/user-manager-sample-popup.html',
silent_redirect_uri:'http://localhost:5000/user-manager-sample-silent.html',
automaticSilentRenew:true,
filterProtocolClaims: true,
loadUserInfo: true
};
var mgr = new Oidc.UserManager(settings);
function iframeSignin() {
mgr.signinSilent({data:'some data'}).then(function(user) {
log("signed in", user);
}).catch(function(err) {
log(err);
});
}
The mgr is an instance of
FYI, we can achieve similar functionality at the server by building a custom middleware and using it as part of the request flow in a MessageHandler. Please let me know if you have any questions.
Thanks,
Soma.