-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e8b46c1
commit 99804db
Showing
10 changed files
with
309 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package chain | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"github.com/paulgoleary/local-luv-proto/crypto" | ||
"github.com/umbracle/ethgo" | ||
"github.com/umbracle/ethgo/contract" | ||
"github.com/umbracle/ethgo/jsonrpc" | ||
) | ||
|
||
type govHelper struct { | ||
gov *contract.Contract | ||
votes *contract.Contract | ||
|
||
k *EcdsaKey | ||
} | ||
|
||
func makeGovHelper(rpcUrl, skHex string, govAddr, votesAddr ethgo.Address) (gh *govHelper, err error) { | ||
|
||
var ec *jsonrpc.Client | ||
if ec, err = jsonrpc.NewClient(rpcUrl); err != nil { | ||
return | ||
} | ||
|
||
var sk *ecdsa.PrivateKey | ||
if sk, err = crypto.SKFromHex(skHex); err != nil { | ||
return | ||
} | ||
|
||
gh = &govHelper{k: &EcdsaKey{SK: sk}} | ||
|
||
if gh.gov, err = LoadContract(ec, "SFLUVGovernor.sol/SFLUVGovernorV0", gh.k, govAddr); err != nil { | ||
return | ||
} | ||
|
||
if gh.votes, err = LoadContract(ec, "SFLUVVotes.sol/SFLUVVotesV1", gh.k, votesAddr); err != nil { | ||
return | ||
} | ||
|
||
return | ||
} | ||
|
||
func (gh *govHelper) mintVote(toAddr ethgo.Address) (err error) { | ||
if err = checkMinterRole(gh.votes, gh.k.Address()); err != nil { | ||
return | ||
} | ||
|
||
if err = TxnDoWait(gh.votes.Txn("mint", toAddr)); err != nil { | ||
return | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package chain | ||
|
||
import ( | ||
"fmt" | ||
"github.com/paulgoleary/local-luv-proto/crypto" | ||
"github.com/stretchr/testify/require" | ||
"os" | ||
"testing" | ||
) | ||
|
||
func TestDAOMumbai(t *testing.T) { | ||
|
||
gh, err := makeGovHelper(os.Getenv("CHAIN_URL"), os.Getenv("CHAIN_SK"), LuvGovMumbaiAddr, LuvVotesMumbaiAddr) | ||
require.NoError(t, err) | ||
|
||
for i := 0; i < 3; i++ { | ||
sk, _ := crypto.RandSK() | ||
ec := EcdsaKey{SK: sk} | ||
|
||
err = gh.mintVote(ec.Address()) | ||
require.NoError(t, err) | ||
|
||
fmt.Printf("address '%v', sk '%v'\n", ec.Address().String(), ec.SKHex()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package chain | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"fmt" | ||
"github.com/paulgoleary/local-luv-proto/crypto" | ||
"github.com/umbracle/ethgo" | ||
"github.com/umbracle/ethgo/contract" | ||
"github.com/umbracle/ethgo/jsonrpc" | ||
"math/big" | ||
) | ||
|
||
type mintHelper struct { | ||
baseCoin *contract.Contract | ||
luvCoin *contract.Contract | ||
|
||
luvAddr ethgo.Address | ||
k *EcdsaKey | ||
} | ||
|
||
func makeMintHelper(rpcUrl, skHex string, luvAddr, baseAddr ethgo.Address) (mh *mintHelper, err error) { | ||
|
||
var ec *jsonrpc.Client | ||
if ec, err = jsonrpc.NewClient(rpcUrl); err != nil { | ||
return | ||
} | ||
|
||
var sk *ecdsa.PrivateKey | ||
if sk, err = crypto.SKFromHex(skHex); err != nil { | ||
return | ||
} | ||
|
||
mh = &mintHelper{k: &EcdsaKey{SK: sk}, luvAddr: luvAddr} | ||
|
||
if mh.luvCoin, err = LoadContract(ec, "SFLUVv1.sol/SFLUVv1", mh.k, luvAddr); err != nil { | ||
return | ||
} | ||
|
||
// MockCoin is ERC20 but also has the 'mint' method in case we need to mint base coins | ||
if mh.baseCoin, err = LoadContract(ec, "MockCoin.sol/MockCoin", mh.k, baseAddr); err != nil { | ||
return | ||
} | ||
|
||
return | ||
} | ||
|
||
// check that the provided key has the MINTER role and - if not - attempt to add it | ||
// note that the configured key has to be an ADMIN of the MINTER role | ||
func checkMinterRole(c *contract.Contract, toAddr ethgo.Address) error { | ||
resp, err := c.Call("MINTER_ROLE", ethgo.Latest) | ||
if err != nil { | ||
return err | ||
} | ||
minterRole, ok := resp["0"].([32]byte) | ||
if !ok { | ||
return fmt.Errorf("should not happen - target contract does not support MINTER_ROLE") | ||
} | ||
|
||
resp, err = c.Call("hasRole", ethgo.Latest, minterRole, toAddr) | ||
if err != nil { | ||
return err | ||
} | ||
hasRole, ok := resp["0"].(bool) | ||
|
||
if !hasRole { | ||
if err = TxnDoWait(c.Txn("grantRole", minterRole, toAddr)); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// this only works if we're allowed to mint against the base coin contract - e.g. it's the mock coin | ||
func (mh *mintHelper) mintBase(toAddr ethgo.Address, amt *big.Int) (err error) { | ||
|
||
var tx contract.Txn | ||
if tx, err = mh.baseCoin.Txn("mint", toAddr, amt); err != nil { | ||
return | ||
} | ||
tx.WithOpts(&contract.TxnOpts{GasLimit: 100_000}) | ||
|
||
if err = TxnDoWait(tx, nil); err != nil { | ||
return | ||
} | ||
|
||
return | ||
} | ||
|
||
// assumes provided key owns sufficient amount in base coin | ||
func (mh *mintHelper) mintLuv(toAddr ethgo.Address, amt *big.Int) (err error) { | ||
|
||
if err = checkMinterRole(mh.luvCoin, mh.k.Address()); err != nil { | ||
return | ||
} | ||
|
||
// function allowance(address owner, address spender) external view returns (uint256); | ||
var resp map[string]any | ||
if resp, err = mh.baseCoin.Call("allowance", ethgo.Latest, mh.k.Address(), mh.luvAddr); err != nil { | ||
return | ||
} | ||
allowance, ok := resp["0"].(*big.Int) | ||
if !ok { | ||
err = fmt.Errorf("should not happen - 'allowance' method did not return proper result") | ||
return | ||
} | ||
if allowance.Cmp(amt) < 0 { | ||
// current allowance is not sufficient | ||
allowance.Sub(amt, allowance) | ||
// function approve(address spender, uint256 amount) public virtual override returns (bool) | ||
if err = TxnDoWait(mh.baseCoin.Txn("approve", mh.luvAddr, allowance)); err != nil { | ||
return | ||
} | ||
} | ||
|
||
if err = TxnDoWait(mh.luvCoin.Txn("depositFor", toAddr, allowance)); err != nil { | ||
return | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.