Skip to content

Instantly share code, notes, and snippets.

@fromjyk
Created November 30, 2018 03:36
Show Gist options
  • Save fromjyk/69afabdaf296bc8dffe9385c11da3fe4 to your computer and use it in GitHub Desktop.
Save fromjyk/69afabdaf296bc8dffe9385c11da3fe4 to your computer and use it in GitHub Desktop.
pragma solidity ^0.4.16;
contract owned {
address public owner;
function owned() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) onlyOwner public {
owner = newOwner;
}
}
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }
contract TokenERC20 { // 토큰의 공용 변수
string public name;
string public symbol;
uint8 public decimals = 18; // 18 자릿수가 권장되는 기본값입니다, 변경하지 마십시오.
uint256 public totalSupply;
// 모든 잔액에 대한 배열을 만듭니다.
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
// 이 이벤트는 블록체인에서 클라이언트에게 ‘이전’을 알려주는 공개 이벤트입니다.
event Transfer(address indexed from, address indexed to, uint256 value);
// 이 이벤트는 블록체인에서 클라이언트에게 ‘승인’을 알려주는 공개 이벤트입니다.
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
// 이 이벤트는 클라이언트에게 ‘소각’을 알려주는 공개 이벤트입니다.
event Burn(address indexed from, uint256 value);
/*
* 생성자 함수
* 컨트랙트 생성자에게 초기 공급 토큰과의 계약을 초기화합니다.
*/
constrctor(
uint256 initialSupply,
string tokenName,
string tokenSymbol
) public {
totalSupply = initialSupply * 10 ** uint256(decimals);// 총 공급량을 십진수로 업데이트 합니다.
balanceOf[msg.sender] = totalSupply; // 작성자에게 모든 초기 토큰을 제공합니다.
name = tokenName; // 표시 목적으로 토큰의 이름을 설정합니다.
symbol = tokenSymbol; // 표시 목적으로 토큰의 기호를 설정합니다.
}
/*
* 내부 전송, 오직 이 계약에서만 호출할 수 있습니다.
*/
function _transfer(address _from, address _to, uint _value) internal {
// 0x0 주소로 전송을 방지합니다. 사용하게 되면 소각을 진행합니다.
require(_to != 0x0);
// 보낸 사람의 자산이 충분한지 확인합니다.
require(balanceOf[_from] >= _value);
// 자산보다 넘게 보내는지 확인합니다.
require(balanceOf[_to] + _value > balanceOf[_to]);
// 향후 주장을 위해 이 정보를 저장합니다.
uint previousBalances = balanceOf[_from] + balanceOf[_to];
// 발신자에게서 자산을 뺍니다.
balanceOf[_from] -= _value;
// 수신자에게 같은 양의 자산을 더합니다.
balanceOf[_to] += _value;
emit Transfer(_from, _to, _value);
// 주장들은 정적 분석을 사용하여 코드에서 버그를 찾습니다. 이것을 빼놓지 마십시오.
assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}
/*
* 토큰 전송
* 계정에서 `_to`에 `_value` 토큰을 전송합니다.
* @param _to 수신자의 주소
* @param _value 보낼 금액
*/
function transfer(address _to, uint256 _value) public returns (bool success) {
_transfer(msg.sender, _to, _value);
return true;
}
/*
* 다른 주소로 토큰 전송
* `_from`을 대신하여 `_value` 토큰을 `_to` 에 전송합니다.
* @param _from 보낸 사람의 주소
* @param _to 받는 사람의 주소
* @param _value 보낼 금액
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= allowance[_from][msg.sender]); // 수량을 확인합니다.
allowance[_from][msg.sender] -= _value;
_transfer(_from, _to, _value);
return true;
}
/*
* 다른 주소에 대한 허용 설정
* `_spender`가 우리를 대신하여 `_value`토큰을 사용할 수 있도록 허용합니다.
* @param _spender 지출할 수 있는 승인된 주소
* @param _value 보낼 수 있는 총 수량
*/
function approve(address _spender, uint256 _value) public
returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/*
* 다른 주소에 대한 허용치 설정 및 알림
* `_spender`가 우리를 대신하여 `_value` 토큰 이상의 토큰을 소비할 수 있게 한 다음, 그것에 대한 컨트랙트를 테스트 합니다.
* @param _spender 지출 권한이 있는 주소
* @param _value 지출할 수 있는 최대 금액
* @param _extraData 승인 된 컨트랙트에 보낼 추가 정보
*/
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;
}
}
/*
* 토큰 소각
* 시스템에서 `_value`토큰을 되돌릴 수 없습니다.
* @param _value 소각할 양
*/
function burn(uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value); // 보낸 사람이 자산이 충분한지 확인합니다.
balanceOf[msg.sender] -= _value; // 발신자의 자산에서 뺍니다.
totalSupply -= _value; // 총 공급량을 업데이트합니다.
emit Burn(msg.sender, _value);
return true;
}
/*
* 다른 계정에서 토큰 소각
* `_from`을 대신하여 시스템에서 `_value` 토큰을 비가역적으로 소각합니다.
* @param _from 보내는 사람의 주소
* @param _value 소각할 총 양
*/
function burnFrom(address _from, uint256 _value) public returns (bool success) {
require(balanceOf[_from] >= _value); // 목표한 잔액이 충분한지 확인합니다.
require(_value <= allowance[_from][msg.sender]); // 허가 여부를 확인합니다.
balanceOf[_from] -= _value; // 목표 잔액에서 차감
allowance[_from][msg.sender] -= _value; // 보낸사람의 허가로부터 차감합니다.
totalSupply -= _value; // 총 공급량을 업데이트합니다.
emit Burn(_from, _value);
return true;
}
}
/******************************************/
/* 향상된 토큰 상태 */
/******************************************/
contract MyAdvancedToken is owned, TokenERC20 {
uint256 public sellPrice;
uint256 public buyPrice;
mapping (address => bool) public frozenAccount;
/* 이 이벤트는 블록체인에서 클라이언트에게 ‘잠금’을 알려주는 공개 이벤트입니다. */
event FrozenFunds(address target, bool frozen);
/* 컨트랙트 작성자에게 초기 공급 토큰과의 계약을 초기화합니다. */
function MyAdvancedToken(
uint256 initialSupply,
string tokenName,
string tokenSymbol
) TokenERC20(initialSupply, tokenName, tokenSymbol) public {}
/* 내부 전송, 이 계약에 의해서만 호출 될 수 있습니다. */
function _transfer(address _from, address _to, uint _value) internal {
require (_to != 0x0); // 0x0 주소로의 전송을 방지하십시오. 사용하면 소각 됩니다.
require (balanceOf[_from] >= _value); // 보낸 사람의 자산이 충분히 있는지 확인합니다.
require (balanceOf[_to] + _value >= balanceOf[_to]); // 오버플로우를 확인합니다.
require(!frozenAccount[_from]); // 발신자의 계정이 잠금되어 있는지 확인합니다.
require(!frozenAccount[_to]); // 수신자의 계정이 잠금되어 있는지 확인합니다.
balanceOf[_from] -= _value; // 발신자의 자산에서 차감합니다.
balanceOf[_to] += _value; // 수신자에게 같을 양을 추가합니다.
emit Transfer(_from, _to, _value);
}
/// @notice 새로운 토큰을 찍어낼 수 있으며 `target` 에 전송합니다.
/// @param 토큰을 받게 되는 타겟 주소
/// @param 찍어낸 토큰의 양을 받습니다.
function mintToken(address target, uint256 mintedAmount) onlyOwner public {
balanceOf[target] += mintedAmount;
totalSupply += mintedAmount;
emit Transfer(0, this, mintedAmount);
emit Transfer(this, target, mintedAmount);
}
/// @notice 동결계좌의 방지 | `target`이 토큰을 보내고 받는것을 허용합니다.
/// @param 동결 대상의 주소
/// @param 어느쪽이든 동결할 수있고 하지 않을 수 있다.
function freezeAccount(address target, bool freeze) onlyOwner public {
frozenAccount[target] = freeze;
emit FrozenFunds(target, freeze);
}
/// @notice 클라이언트가 `newBuyPrice`에 대한 토큰을 구입하고 `newSellPrice`에 대한 토큰을 판매하도록 허용합니다.
/// @param newSellPrice 컨트랙트에 판매 할 수 있는 가격
/// @param newBuyPrice 컨트랙트로 부터 팔 수 있는 가격
function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner public {
sellPrice = newSellPrice;
buyPrice = newBuyPrice;
}
/// @notice 이더리움을 보내서 컨트랙터에서 토큰을 구입합니다.
function buy() payable public {
uint amount = msg.value / buyPrice; // 수량을 계산합니다.
_transfer(this, msg.sender, amount); // 전송을 발생시킵니다.
}
/// @notice 컨트랙트에 `amount`만큼의 토큰 판매
/// @param ‘amount’ 매매할 토큰의 금액
function sell(uint256 amount) public {
address myAddress = this;
require(myAddress.balance >= amount * sellPrice); // 컨트랙트에 충분한 이더리움이 있는지 확인합니다.
_transfer(msg.sender, this, amount); // 전송을 발생시킵니다.
msg.sender.transfer(amount * sellPrice); // 이더리움을 판매자에게 보냅니다. 재귀공격을 피하려면 이 작업을 마지막으로 수행하는 것이 중요합니다.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment