30분만에 ICO하기
안녕하세요. 오늘은 조금 자극적인 제목을 가지고 와봤습니다. 요즘 ICO 많이들 참여하시고, 직접 하시는 분들도 많이 계신데요. ICO에 필요한 토큰을 단 30분 만에 발행하는 방법을 소개해볼까 합니다.
준비물은 단 한 가지. mist 지갑입니다. 이 mist 지갑에는 스마트 컨트랙을 발행하는 기능이 있는데요. 여기에 아래와 같이 ERC20 표준에 해당하는 코드를 넣고 발행하기만 하면, 순식간에 토큰 하나가 뚝딱 만들어집니다.
코드 예시 :
pragma solidity ^0.4.16; interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } contract TokenERC20 { // Public variables of the token string public name; string public symbol; uint8 public decimals = 18; // 18 decimals is the strongly suggested default, avoid changing it uint256 public totalSupply; // This creates an array with all balances mapping (address => uint256) public balanceOf; mapping (address => mapping (address => uint256)) public allowance; // This generates a public event on the blockchain that will notify clients event Transfer(address indexed from, address indexed to, uint256 value); // This notifies clients about the amount burnt event Burn(address indexed from, uint256 value); /** * Constructor function * * Initializes contract with initial supply tokens to the creator of the contract */ function TokenERC20( uint256 initialSupply, string tokenName, string tokenSymbol ) public { totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens name = tokenName; // Set the name for display purposes symbol = tokenSymbol; // Set the symbol for display purposes } /** * Internal transfer, only can be called by this contract */ function _transfer(address _from, address _to, uint _value) internal { // Prevent transfer to 0x0 address. Use burn() instead require(_to != 0x0); // Check if the sender has enough require(balanceOf[_from] >= _value); // Check for overflows require(balanceOf[_to] + _value > balanceOf[_to]); // Save this for an assertion in the future uint previousBalances = balanceOf[_from] + balanceOf[_to]; // Subtract from the sender balanceOf[_from] -= _value; // Add the same to the recipient balanceOf[_to] += _value; Transfer(_from, _to, _value); // Asserts are used to use static analysis to find bugs in your code. They should never fail assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } /** * Transfer tokens * * Send `_value` tokens to `_to` from your account * * @param _to The address of the recipient * @param _value the amount to send */ function transfer(address _to, uint256 _value) public { _transfer(msg.sender, _to, _value); } /** * Transfer tokens from other address * * Send `_value` tokens to `_to` on behalf of `_from` * * @param _from The address of the sender * @param _to The address of the recipient * @param _value the amount to send */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(_value <= allowance[_from][msg.sender]); // Check allowance allowance[_from][msg.sender] -= _value; _transfer(_from, _to, _value); return true; } /** * Set allowance for other address * * Allows `_spender` to spend no more than `_value` tokens on your behalf * * @param _spender The address authorized to spend * @param _value the max amount they can spend */ function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } /** * Set allowance for other address and notify * * Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it * * @param _spender The address authorized to spend * @param _value the max amount they can spend * @param _extraData some extra information to send to the approved contract */ function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { spender.receiveApproval(msg.sender, _value, this, _extraData); return true; } } /** * Destroy tokens * * Remove `_value` tokens from the system irreversibly * * @param _value the amount of money to burn */ function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); // Check if the sender has enough balanceOf[msg.sender] -= _value; // Subtract from the sender totalSupply -= _value; // Updates totalSupply Burn(msg.sender, _value); return true; } /** * Destroy tokens from other account * * Remove `_value` tokens from the system irreversibly on behalf of `_from`. * * @param _from the address of the sender * @param _value the amount of money to burn */ function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); // Check if the targeted balance is enough require(_value <= allowance[_from][msg.sender]); // Check allowance balanceOf[_from] -= _value; // Subtract from the targeted balance allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance totalSupply -= _value; // Update totalSupply Burn(_from, _value); return true; } }
|
어때요 정말 쉽지 않나요? SUPERTOKEN이라는 이름을 가진 토큰이 하나 만들어졌습니다. 이 과정에서 가장 어려운 일은 mist 지갑을 준비하는 일입니다. mist 지갑은 이더리움 네트워크와 싱크를 맞추기 위해서 상당한 시간이 소요됩니다. 적어도 하루는 잡아야 하고요. PC 사양에 따라서 오래 걸릴 경우에는 일주일 이상 소요될 수 있습니다.
여기서 우리는 몇 가지 시사점을 얻을 수 있습니다.
1. 생각보다 많은 ICO들이 이런 허접한 컨트랙을 가지고 ICO를 진행합니다. 컨트랙이 공개된 몇몇 해외 유명 ICO들과 국내 ICO들을 뒤져보면, 30분 만에 찍어낸 수준으로 토큰을 발행한 곳들이 많습니다. ICO에 거액이 투자되는데도 사람들은 내용을 모르고 너무 쉽게 쉽게들 투자하죠.
2. 그렇지만 토큰 발행에는 그닥 많은 기능이 필요하지 않은 게 사실이기도 합니다. 요즘 ICO에 필수라고 여겨지는 KYC나 토큰 전송 기능, 아무나 컨트랙에 손대지 못하게 하는 권한 분배, 최근 NEM 해킹 사태처럼 비상 사태가 발생했을 때 대처할 수 있는 기능들, DApp 개발 후에 포크를 위한 포크 기능 정도면 충분합니다. 그러나 이정도도 없이 30분 완성 컨트랙으로 적당히 ICO를 때우려는 사람들이 있는 것도 사실이죠.
3. ICO는 끝이 아니라 시작입니다. 많은 ICO 주최자들과 심지어는 참여자들까지도 간과하고 있는 사실이 바로 ICO는 시작에 불과하다는 점입니다. 주최자들은 물론이고 주최자들을 감시해야 할 참여자들까지도 투더문을 외치는 모습이 바람직하다고만 볼 수는 없습니다. ICO는 DApp을 만들고 사람들이 원하는 서비스를 제공하기 위해 시작하는 것인데, ICO로 거액을 모았다고 해서 그것이 끝인 것처럼 행동해서는 안된다는 것이죠.
마치며, 첫 ICO를 준비하는 개발자들에게 도움이 될만한 것들을 적어봅니다.
1) minime token (https://github.com/Giveth/minime)
미니미 토큰은 포크를 하기 위해 적합한 라이브러리입니다. 소스들을 뜯어보면 알겠지만, 정말 손쉽게 다음 버전의 토큰을 만들어낼 수 있습니다. 토큰 배분 후에 개발을 진행하고, 개발 후에 새로운 기능을 추가해서 토큰 홀더들에게 새 토큰을 발행하는 것까지 이미 완성되어 있습니다. 실제 사용할 때는 약간 수정할 부분들이 있지만, 사용하기에 큰 무리가 없습니다.
2) ICO Wizard(https://wizard.oracles.org/)
ICO Wizard는 ICO를 준비하는 사람들을 위해서 만들어졌고, 원하는 정보들을 입력하면 필요한 코드를 생성해줍니다. 그대로 사용하기는 무리가 있지만 베이스가 없는 상황에서 구조를 설계하는 것엔 많은 도움이 됩니다.
글이 재밌거나 유용하다면 좋아요를 눌러주세요.
원팡
2018.02.22 20:22
와!! 간만에 제대로 된 정보글 감사합니다! ㅎ
역시 투자는 신중하게 접근해야겠죠!