@@ -41,6 +41,8 @@ import (
4141 "sync"
4242 "time"
4343
44+ "github.com/ethereum/go-ethereum/accounts/abi"
45+
4446 "github.com/ethereum/go-ethereum/accounts"
4547 "github.com/ethereum/go-ethereum/accounts/keystore"
4648 "github.com/ethereum/go-ethereum/common"
@@ -83,11 +85,15 @@ var (
8385 noauthFlag = flag .Bool ("noauth" , false , "Enables funding requests without authentication" )
8486 logFlag = flag .Int ("loglevel" , 3 , "Log level to use for Ethereum and the faucet" )
8587
86- fixGasPrice = flag .Int64 ("faucet.fixedprice" , 0 , "Will use fixed gas price if specified" )
88+ bep2eContracts = flag .String ("bep2eContracts" , "" , "the list of bep2p contracts" )
89+ bep2eSymbols = flag .String ("bep2eSymbols" , "" , "the symbol of bep2p tokens" )
90+ bep2eAmounts = flag .String ("bep2eAmounts" , "" , "the amount of bep2p tokens" )
91+ fixGasPrice = flag .Int64 ("faucet.fixedprice" , 0 , "Will use fixed gas price if specified" )
8792)
8893
8994var (
90- ether = new (big.Int ).Exp (big .NewInt (10 ), big .NewInt (18 ), nil )
95+ ether = new (big.Int ).Exp (big .NewInt (10 ), big .NewInt (18 ), nil )
96+ bep2eAbiJson = `[ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "inputs": [], "name": "totalSupply", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "symbol", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getOwner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "sender", "type": "address" }, { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" } ]`
9197)
9298
9399var (
@@ -110,18 +116,51 @@ func main() {
110116 amounts [i ] = strings .TrimSuffix (amounts [i ], "s" )
111117 }
112118 }
119+ bep2eNumAmounts := make ([]string , 0 )
120+ if bep2eAmounts != nil && len (* bep2eAmounts ) > 0 {
121+ bep2eNumAmounts = strings .Split (* bep2eAmounts , "," )
122+ }
123+
124+ symbols := make ([]string , 0 )
125+ if bep2eSymbols != nil && len (* bep2eSymbols ) > 0 {
126+ symbols = strings .Split (* bep2eSymbols , "," )
127+ }
113128
129+ contracts := make ([]string , 0 )
130+ if bep2eContracts != nil && len (* bep2eContracts ) > 0 {
131+ contracts = strings .Split (* bep2eContracts , "," )
132+ }
133+
134+ if len (bep2eNumAmounts ) != len (symbols ) || len (symbols ) != len (contracts ) {
135+ log .Crit ("Length of bep2eContracts, bep2eSymbols, bep2eAmounts mismatch" )
136+ }
137+
138+ bep2eInfos := make (map [string ]bep2eInfo , 0 )
139+ for idx , s := range symbols {
140+ n , ok := big .NewInt (0 ).SetString (bep2eNumAmounts [idx ], 10 )
141+ if ! ok {
142+ log .Crit ("failed to parse bep2eAmounts" )
143+ }
144+ amountStr := big .NewFloat (0 ).Quo (big .NewFloat (0 ).SetInt (n ), big .NewFloat (0 ).SetInt64 (params .Ether )).String ()
145+
146+ bep2eInfos [s ] = bep2eInfo {
147+ Contract : common .HexToAddress (contracts [idx ]),
148+ Amount : * n ,
149+ AmountStr : amountStr ,
150+ }
151+ }
114152 // Load up and render the faucet website
115153 tmpl , err := Asset ("faucet.html" )
116154 if err != nil {
117155 log .Crit ("Failed to load the faucet template" , "err" , err )
118156 }
119157 website := new (bytes.Buffer )
120158 err = template .Must (template .New ("" ).Parse (string (tmpl ))).Execute (website , map [string ]interface {}{
121- "Network" : * netnameFlag ,
122- "Amounts" : amounts ,
123- "Recaptcha" : * captchaToken ,
124- "NoAuth" : * noauthFlag ,
159+ "Network" : * netnameFlag ,
160+ "Amounts" : amounts ,
161+ "Recaptcha" : * captchaToken ,
162+ "NoAuth" : * noauthFlag ,
163+ "Bep2eInfos" : bep2eInfos ,
125164 })
126165 if err != nil {
127166 log .Crit ("Failed to render the faucet template" , "err" , err )
@@ -162,7 +201,7 @@ func main() {
162201 ks .Unlock (acc , pass )
163202
164203 // Assemble and start the faucet light service
165- faucet , err := newFaucet (genesis , * ethPortFlag , enodes , * netFlag , * statsFlag , ks , website .Bytes ())
204+ faucet , err := newFaucet (genesis , * ethPortFlag , enodes , * netFlag , * statsFlag , ks , website .Bytes (), bep2eInfos )
166205 if err != nil {
167206 log .Crit ("Failed to start faucet" , "err" , err )
168207 }
@@ -181,6 +220,12 @@ type request struct {
181220 Tx * types.Transaction `json:"tx"` // Transaction funding the account
182221}
183222
223+ type bep2eInfo struct {
224+ Contract common.Address
225+ Amount big.Int
226+ AmountStr string
227+ }
228+
184229// faucet represents a crypto faucet backed by an Ethereum light client.
185230type faucet struct {
186231 config * params.ChainConfig // Chain configurations for signing
@@ -201,9 +246,12 @@ type faucet struct {
201246 update chan struct {} // Channel to signal request updates
202247
203248 lock sync.RWMutex // Lock protecting the faucet's internals
249+
250+ bep2eInfos map [string ]bep2eInfo
251+ bep2eAbi abi.ABI
204252}
205253
206- func newFaucet (genesis * core.Genesis , port int , enodes []* discv5.Node , network uint64 , stats string , ks * keystore.KeyStore , index []byte ) (* faucet , error ) {
254+ func newFaucet (genesis * core.Genesis , port int , enodes []* discv5.Node , network uint64 , stats string , ks * keystore.KeyStore , index []byte , bep2eInfos map [ string ] bep2eInfo ) (* faucet , error ) {
207255 // Assemble the raw devp2p protocol stack
208256 stack , err := node .New (& node.Config {
209257 Name : "geth" ,
@@ -222,6 +270,10 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
222270 if err != nil {
223271 return nil , err
224272 }
273+ bep2eAbi , err := abi .JSON (strings .NewReader (bep2eAbiJson ))
274+ if err != nil {
275+ return nil , err
276+ }
225277 // Assemble the Ethereum light client protocol
226278 if err := stack .Register (func (ctx * node.ServiceContext ) (node.Service , error ) {
227279 cfg := eth .DefaultConfig
@@ -261,14 +313,16 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
261313 client := ethclient .NewClient (api )
262314
263315 return & faucet {
264- config : genesis .Config ,
265- stack : stack ,
266- client : client ,
267- index : index ,
268- keystore : ks ,
269- account : ks .Accounts ()[0 ],
270- timeouts : make (map [string ]time.Time ),
271- update : make (chan struct {}, 1 ),
316+ config : genesis .Config ,
317+ stack : stack ,
318+ client : client ,
319+ index : index ,
320+ keystore : ks ,
321+ account : ks .Accounts ()[0 ],
322+ timeouts : make (map [string ]time.Time ),
323+ update : make (chan struct {}, 1 ),
324+ bep2eInfos : bep2eInfos ,
325+ bep2eAbi : bep2eAbi ,
272326 }, nil
273327}
274328
@@ -371,6 +425,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
371425 URL string `json:"url"`
372426 Tier uint `json:"tier"`
373427 Captcha string `json:"captcha"`
428+ Symbol string `json:"symbol"`
374429 }
375430 if err = conn .ReadJSON (& msg ); err != nil {
376431 return
@@ -475,13 +530,31 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
475530 fund bool
476531 timeout time.Time
477532 )
478- if timeout = f .timeouts [username ]; time .Now ().After (timeout ) {
479- // User wasn't funded recently, create the funding transaction
480- amount := new (big.Int ).Mul (big .NewInt (int64 (* payoutFlag )), ether )
481- amount = new (big.Int ).Mul (amount , new (big.Int ).Exp (big .NewInt (5 ), big .NewInt (int64 (msg .Tier )), nil ))
482- amount = new (big.Int ).Div (amount , new (big.Int ).Exp (big .NewInt (2 ), big .NewInt (int64 (msg .Tier )), nil ))
483533
484- tx := types .NewTransaction (f .nonce + uint64 (len (f .reqs )), address , amount , 21000 , f .price , nil )
534+ if timeout = f .timeouts [username ]; time .Now ().After (timeout ) {
535+ var tx * types.Transaction
536+ if msg .Symbol == "BNB" {
537+ // User wasn't funded recently, create the funding transaction
538+ amount := new (big.Int ).Mul (big .NewInt (int64 (* payoutFlag )), ether )
539+ amount = new (big.Int ).Mul (amount , new (big.Int ).Exp (big .NewInt (5 ), big .NewInt (int64 (msg .Tier )), nil ))
540+ amount = new (big.Int ).Div (amount , new (big.Int ).Exp (big .NewInt (2 ), big .NewInt (int64 (msg .Tier )), nil ))
541+
542+ tx = types .NewTransaction (f .nonce + uint64 (len (f .reqs )), address , amount , 21000 , f .price , nil )
543+ } else {
544+ tokenInfo , ok := f .bep2eInfos [msg .Symbol ]
545+ if ! ok {
546+ f .lock .Unlock ()
547+ log .Warn ("Failed to find symbol" , "symbol" , msg .Symbol )
548+ continue
549+ }
550+ input , err := f .bep2eAbi .Pack ("transfer" , address , & tokenInfo .Amount )
551+ if err != nil {
552+ f .lock .Unlock ()
553+ log .Warn ("Failed to pack transfer transaction" , "err" , err )
554+ continue
555+ }
556+ tx = types .NewTransaction (f .nonce + uint64 (len (f .reqs )), tokenInfo .Contract , nil , 420000 , f .price , input )
557+ }
485558 signed , err := f .keystore .SignTx (f .account , tx , f .config .ChainID )
486559 if err != nil {
487560 f .lock .Unlock ()
0 commit comments